等到未知数量的可观察物完成

时间:2019-01-25 19:05:49

标签: angular rxjs

有很多类似性质的问题,我认为这有点不同。

考虑以下代码:

arr = [];

this.service1.getItem()
  .subscribe(item => {
    Object.entries(item).forEach(([key, value]) => {
    if (some_condition_true) {
      this.service2.getSomeItems2(value.prop1).pipe(first())
        .subscribe(result => value.xyz = result);
        this.arr.push(value);
    }
 });

});

// This line should execute only after the 'forEach' above completes
this.someService.someMethod(arr);

问题是我不知道将service2.getSomeItems2呼叫多少次。

此外,zipforkJoin占用Observables,但我已经订阅了。也许我可以tap代替subscribe。但是事实仍然是未知数。

2 个答案:

答案 0 :(得分:0)

怎么样?

this.service1.getItem()
  .pipe(switchMap(items => {
      const itemReqs = Object.entries(items)
                       .filter(v => some_condition_true_or_false)
                       .map(item => this.service2.getSomeItems2(item.prop1).pipe(first()));

     return forkJoin(itemReqs);

  }))
  .subscribe(data_from_service_2_calls => {
     data_from_service_2_calls.forEach(v => console.log(v))
   });

可能存在语法错误,但是我认为这是您想要的。请记住,您应该避免在内部订阅。

希望有帮助!

答案 1 :(得分:0)

如果可能的话,您应该订阅而不是提早订阅,并将您的逻辑转移到Observables的pipe中。

这里的技巧是将第一个请求(使用mergeMapswitchMap)映射到多个第二个请求的联合输出(使用forkJoin)。

我认为它应该像这样:

this.service1.getItem()
  .pipe(
    mergeMap(item => forkJoin(getItemRequests(item)))
  ).subscribe(arr => this.someService.someMethod(arr));

getItemRequests(item: any): Observable<any>[] {
  return Object.entries(item)
    .filter(([key, value]) => some_condition_true)
    .map(([key, value]) => this.service2.getSomeItems2(value.prop1)
      .pipe(
        first(),
        tap(result => value.xyz = result),
        map(result => value)
      )
    );
}