有没有办法在同一个变量下有一个Subject和Observable

时间:2018-06-15 10:45:42

标签: typescript rxjs

目前我有这样的代码:

const exampleSubject = new Subject<any>();
const example$ = exampleSubject.pipe(...);
// later emit some data to that subject and do things with observable, like subscribtion

并且它工作正常,但是有一种方法可以在同一个变量/属性下同时使用SubjectObservable并同时转换数据,例如:

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(使用管道或其他方式使用运算符)并仍然从外部发出数据?

1 个答案:

答案 0 :(得分:2)

不,没有。 SubjectObservable的子类型。 pipeObservable一起使用,当然,它也可以与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>nextnext(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

但是,当然,你需要两个变量/属性