目前我有这样的代码:
const exampleSubject = new Subject<any>();
const example$ = exampleSubject.pipe(...);
// later emit some data to that subject and do things with observable, like subscribtion
并且它工作正常,但是有一种方法可以在同一个变量/属性下同时使用Subject
和Observable
并同时转换数据,例如:
const example$ = (a subject constructor).pipe(...);
// later execute example$.emit(...), example$.subscribe(...), etc.
你可能会注意到pipe
运算符总是返回Observable<T>
实例,这就是问题所在,但也许我错过了一些功能?
我宁愿避免创造像:
这样的小怪物let subscriber: Subscriber<any>;
const example$ = (new Observable<any>((sub) => { subscriber = sub; })).pipe(...);
// later calling subscriber.next(...), subscriber.complete(...), etc.
那么有没有办法在同一个变量下使用Subject和Observable(使用管道或其他方式使用运算符)并仍然从外部发出数据?
答案 0 :(得分:2)
不,没有。 Subject
是Observable
的子类型。 pipe
与Observable
一起使用,当然,它也可以与Subject
一起使用,但是由于调用,您获得了Observable
,而不是Subject
那个功能。
通过pipe
将运算符链接到观察者的结果“喂”数据毫无意义,因为通过调用此类运算符,您说您希望结果Observable
成为流来自原始Observable
数据流的转换值。我的意思是,您可以使用map
来改变数字流并获得它们的正方形。将数据“提供”到可观察结果的目的是什么?
const subject = new Subject<number>();
const squares$ = subject.pipe(map(item => item*item));
squares$.subscribe(value => console.log(value));
squares$.next(2); // we get 4 in the console.
您可以使用充当数据操作符的函数来实现此目的:
const square = (value: number) => value*value;
const subject = new Subject<number>();
subject.subscribe(value => console.log(value));
subject.next(square(2)); // we get 4 in the console.
当然,您可以通过创建Subject
的新子类来简化此操作,该子类接受转换值的函数:
const transSubject = new TransSubject<number>(value => value*value);
transSubject.subscribe(value => console.log(value));
transSubject.next(2); // we get 4 in the console.
基本上,这样的类会在其构造函数中存储一组转换函数,然后覆盖next
方法,以便在将结果值传递给超类{{1}之前按顺序应用转换函数方法。
当然,这仍然存在问题,即一旦定义了next
的数据类型,就无法返回其他类型。当然,您可以定义TransSubject
类,以便TransSubject<T, K>
为next
而next(value: K)
将定义为subscribe
,但这会非常复杂。您应该确保构造函数中的函数组合是subscribe({next: (value: T) => any, complete: ...})
类型。你可以有类似的东西:
K => T
在这种情况下,我们有const sbj = new TransSubject<string, number>((value: number) => value*value, (value: number) => value.toString());
和number => number
因此,组合number => string
与匹配类型参数。
然而,正如我所说,使用简单的函数和使用普通的observable来做这件事会更容易。你甚至可以做一个闭包来简化它:
number => string
但是,当然,你需要两个变量/属性