【问题标题】:How to call another HTTP request after forkJoin is completed (RxJS)?forkJoin 完成后如何调用另一个 HTTP 请求(RxJS)?
【发布时间】:2020-12-15 14:36:47
【问题描述】:

我已经看了很长时间,但我真的没有弄清楚如何“正确”地做到这一点。所有其他答案要么被弃用,要么以相反的顺序执行。

我想做的是,我想并行发送一堆 HTTP 请求,因此是 forkJoin。然后只有当它们完成时,我想调用另一个 HTTP 请求(现在在 submitOrder() 中)。

然后在某个时候,如果第一个 HTTP 请求成功,我想再次将我的对象标记为不脏。

这段代码有效,但我知道这确实不是“正确”的做法,因为它在订阅中调用订阅。

请问,真正的 RxJs 方式是什么?

forkJoin(obsArray).subscribe(res => {
            console.log('All were resolved');
            this.products.forEach(element => {
                this.isNotDirtyAnymore();
            });
            this.submitOrder();
        });


submitOrder() {
        this.service.submitOrder(this.id).subscribe(response => {
            console.log('Order was submitted');
        }, error => {
            console.log(error);
        });
    }

【问题讨论】:

  • 在forkJoin之后不能使用switchMap吗?
  • 至少不链接,如 forkJoin(array).switchMap() - 抱怨它不是 Observable 的一部分。这可能与 RxJS 的更新有关。

标签: angular http rxjs reactive-programming


【解决方案1】:

这是我上面评论的一个例子(未经测试):

   forkJoin([
        this.service.callItem1,
        this.service.callItem2
    ]).pipe(
        tap(([resp1, resp2]: [any, any])=> {
            this.products.forEach(element => {
                this.isNotDirtyAnymore();
            });
        }),
        switchMap(([resp1, resp2]: [any, any]) => this.service.submitOrder(this.id))
    ).subscribe(response => {
        // if you don't need to do this in the tap above you can do it here
        this.products.forEach(element => {
            this.isNotDirtyAnymore();
        });
        console.log('Order was submitted');
    }, error => {
        console.log(error);
    });

【讨论】:

    【解决方案2】:

    如果您不需要 forkJoin 的结果,您可以这样做:

    concat(
      forkJoin(obsArray),
      this.service.submitOrder(this.id)
    ).subscribe({
      complete: () => { // This will be triggered only when `concat` completes which means both source Observables complete (won't emit error).
        this.products.forEach(element => {
          this.isNotDirtyAnymore();
        });
      },
    })
    

    确保您导入 import { concat } from 'rxjs'; 而不是来自 rxjs/operators

    【讨论】:

    • 如果我需要来自 forkJoin 的结果怎么办?例如。我想看看其中一个是否有错误。
    • 如果其中任何一个发出错误,则错误将传播到subscribe,您可以在其中使用error 处理程序进行处理。
    【解决方案3】:

    由于forkJoin 实际上返回了一个新的可观察对象,您可以将其视为普通的可观察对象。然后可以使用普通的高阶运算符,switchMap,contactMap...并将副作用放入tap。例如:

    forkJoin(obsArray).pipe(
      tap(() => {
        console.log('All were resolved');
        this.products.forEach(element => this.isNotDirtyAnymore()),
      }),
      switchMap(() => submitOrder()),
    });
    

    【讨论】:

    • 然后我会 .subscribe() 在它的末尾那个东西?还是已经这样做了?
    • 是的,你可以通过 subscribe() 来触发它。或者,如果您使用 Angular,请使用异步管道。平台级糖会自动为您处理退订。
    【解决方案4】:

    您可以使用管道运算符。

    来自http://reactivex.io/rxjs/class/es6/Observable.js~Observable.html的示例:

    import { map, filter, scan } from 'rxjs/operators';
    
    Rx.Observable.interval(1000)
      .pipe(
         filter(x => x % 2 === 0),
         map(x => x + x),
         scan((acc, x) => acc + x)
       ).subscribe(x => console.log(x))
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-12-14
      • 2019-05-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-05-03
      • 1970-01-01
      • 2018-10-12
      相关资源
      最近更新 更多