rxjs如何观察未完成的可观察对象的集合

时间:2020-11-10 19:12:16

标签: angular rxjs

我有一堆可观察变量(打字稿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}},但我敢肯定,只要得到这个,我就可以找出其余的那些。)

2 个答案:

答案 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()是服务启动时运行的任何代码块。 (在您首次致电allregister之前)

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,因为它们是自动退订的。

实时演示:https://stackblitz.com/edit/rxjs-ldjj83?file=index.ts