我有一堆可观察变量(打字稿Observable<boolean>
),每一个都发出多次然后完成,我想在它们完成时将它们从集合中删除,但是当它们仍然处于活动状态时,我需要知道最新的值从他们。如果设置没有改变,我会得到这样的东西:
function all(inputs: Observable<boolean>[]) {
return combineLatest([...inputs]).pipe(map((values) => values.every(v=>v)));
}
但是我需要能够注册新的可观察对象,并在它们完成时将它们从输入列表中删除...
class AssentService {
all(): Observable<boolean> { /* ??? */ }
register(input: Observable<boolean>) { /* ??? */ }
}
all
仅被调用一次(可能在任何寄存器调用之前),但是register
可以被调用多次,并且需要添加该输入直到完成(最终我需要的不仅仅是{ {1}},但我敢肯定,只要得到这个,我就可以找出其余的那些。)
答案 0 :(得分:1)
这是一个自定义运算符,可通过映射实现CombineLatest,并且每次发出任何流时都仅发出当前正在运行的流的数组。
这是一个高阶运算符,因此您将像mergeAll()
或concatAll()
那样使用它,因为它需要可观察的数据流。
combineLatestAll(){
return stream$ => defer(() => {
const register = new Map<number, any>();
return stream$.pipe(
mergeMap((inner$: Observable<any>, index: number) => inner$.pipe(
finalize(() => register.delete(index)),
map(payload => {
register.set(index, payload);
return Array.from(register.values());
})
))
)
})
}
您可以随意使用它,但这是一个简单的方法(如果有限制的话)。
class AssentService {
private _registered$ = new Subject<Observable<boolean>>();
all(): Observable<boolean[]> {
return this._registered$.pipe(
combineLatestAll()
)
}
register(input: Observable<boolean>) {
this._registered$.next(input);
}
}
为什么要限制?此方法会多播register
,但您在combineLatestAll()
之后的通话中只能all()
。因此,如果消费者先拨打all()
然后注册,这将达到我预期的方式。
您可以缓存最近的结果并在所有订阅者之间共享。在这种情况下,init()
是服务启动时运行的任何代码块。 (在您首次致电all
或register
之前)
class AssentService {
private _registered$ = new Subject<Observable<boolean>>();
private _cashed$ = _registered$.pipe(
combineLatestAll(),
shareReplay(1)
);
/*** init(){ ***/
this._cashed$.subscibe();
/*** } ***/
all(): Observable<boolean[]> {
return this.cashed$;
}
register(input: Observable<boolean>) {
this._registered$.next(input);
}
}
答案 1 :(得分:0)
您可以使用mergeAll()
将高阶Observable合并到链中:
subject
.pipe(
mergeAll(),
)
.subscribe({
next: console.log,
complete: () => console.log('completed')
});
...
subject.next(timer(1000));
subject.next(timer(1000));
subject.complete();
仅在所有嵌套的Observables完成之后以及源subject
完成时,才调用complete处理程序。您不需要删除完整的Observable,因为它们是自动退订的。