【问题标题】:How to execute and get result of sequential HTTP calls using RxJS如何使用 RxJS 执行并获取顺序 HTTP 调用的结果
【发布时间】:2020-11-16 12:29:37
【问题描述】:

我想按顺序进行几次 HTTP 调用,每次调用后,我想检查结果并进行另一个调用并显示消息等。在某些情况下继续下一个调用,某些情况下在显示消息后中断该调用.另一方面,我还需要在每次调用时使用catchError 块(或者可能对所有调用都使用一个块,但每次调用都使用一个块会更好)。

因此,假设我有一个创建、更新和删除调用,如下所示。如何获取每个调用的响应并检查响应然后执行另一个调用?

我已经尝试过switchMapiif,我正在寻找使用其中一个的解决方案。有什么建议吗?

this.service.create('/api/employee').subscribe(resp1 => {
    this.service.update('/api/salary/', id).subscribe(resp2 => {
        this.service.delete('/api/education/', id).subscribe(resp3 => {

        // I need to get response of each call from starting thr first and then continue of 
        // break according to the condition of the response

  });
});

【问题讨论】:

    标签: javascript angular typescript rxjs


    【解决方案1】:

    在这里使用switchMap 是一个好方法:

    this.service.create('/api/employee')
     .pipe(switchMap((resp) => {
        if(fulfillsCondition(resp)) {
           return this.service.update(...);
        }
        return this.service.delete(...);
    })).subscribe();
    

    【讨论】:

    • 感谢您的回复,看起来不错,我会尽快尝试。但是catchError 块呢?我还需要使用它们来捕获错误并在 catchError 块中添加一个 if 块。您能否通过添加一个空的 if 来添加该块(因为通常我会遇到 void 错误,最好在您的帮助下看到正确的用法:)
    • 您介意更新一下我最后的评论吗?问候。
    • 它似乎有效,但我需要在每次调用的正确位置上添加 catchError((err: any) => {...}(也可以为每次调用使用单个 catch 块。您能否更新您的代码到执行此操作?提前致谢。
    • 我有一些问题,与这种方法有关:1 我认为return EMPTYreturn NEVER ara 用于在任何时候完成流。真的吗? 2. 如果我们想让流在switchMap 块中继续,该怎么办? 3. 据我了解,switchMap 的想法是按顺序 执行 HTTP 调用,并在其块中进行一些操作和错误处理。这是真的吗?
    【解决方案2】:

    我不确定这里还有什么要说的。

    值得注意的是,EMPTY 是一个 RxJs 流,它什么都不发出并立即完成。它有点像“中断”(以一种非常松散的方式。从流中“中断”的方式可能非常依赖于上下文)。

    this.service.create('/api/employee').pipe(
      catchError(err1 => {
        // do some stuff
        return throwError(err1);
      }),
      switchMap(resp1 => {
        // do some stuffs
        if(someCondition(resp1)){ 
          return this.service.update('/api/salary/', id).pipe(
            catchError(err2 => {
              // do some stuff
              return throwError(err2);
            }),
          );
        }
        return EMPTY;
      }),
      switchMap(resp2 => {
        // do some stuff
        if(someCondition(resp2)){ 
          return this.service.delete('/api/education/', id).pipe(
            catchError(err3 => {
              // do some stuff
              return throwError(err3);
            }),
          );
        }
        return EMPTY;
      }),
    ).subscribe({
      next: resp3 => { /*do some stuff*/ },
      complete: () => { /*Your stream is done*/ },
      eror: err => { /*All re-thrown errors end up here */ }
    });
    

    更新

    使用tap 帮助理解流

    tap 是一个运算符,它返回它接收到的相同流。它不能对您的流进行任何更改,但它可以查看在任何给定点发生的情况。这可能是帮助您理解的有用工具。

    http1().pipe(
      tap({
        next: val => console.log("Result from http1 call: ", val),
        complete: () => console.log("http1 call completed"),
        error: err => console.log("http1 call errored: ", err)
      })
      switchMap(val => http2(val).pipe(
        tap({
          next: val => console.log("Result from http2 call: ", val),
          complete: () => console.log("http2 completed"),
          error: err => console.log("http2 call errored: ", err)
        })
      )),
      tap({
        next: val => console.log("Result from switchMap operator: ", val),
        complete: () => console.log("switchMap completed"),
        error: err => console.log("switchMap (http1 or http2 call) errored: ", err)
      })
    ).subscribe()
    

    在这里我们可以看到switchMap 之前和之后发生的情况。您可以看到,在这种情况下,switchMap 从 http1 获取值并从 http2 发出值。

    因为 switchMap 在生成 http2 之前会等待来自 http1 的值,所以一个副作用是 http2 直到 http1 发出后才会启动。这确实意味着这些调用是按顺序执行的,但如果 http1 多次发出,情况就会变得更加复杂。

    更多关于:

    【讨论】:

    • 投了赞成票,但无论如何,我无法让它发挥作用。但我认为我犯了一个错误。
    • 我有一些问题,与这种方法有关:1 我认为return EMPTYreturn NEVER ara 用于在任何时候完成流。真的吗? 2. 如果我们想让流在switchMap 块中继续,该怎么办? 3. 据我了解,switchMap 的想法是按顺序 执行 HTTP 调用,并在其块中进行一些操作和错误处理。这是真的吗?
    • NEVEREMPTY 从不发出任何值。 NEVER 是一个永远“活着”的流。它永远不会完成,必须取消订阅。 EMPTY 立即完成。 switchMap 接受一个值流并使用这些值来计算和订阅一个流。它订阅的流是根据最新值计算的流(其他所有内容都被删除)。使用mergeMap,您永远不会丢弃旧流,只需将它们合并到新流中即可。
    • switchMap 通常用于 HTTP 调用,因为您期望只有一个响应,并且 switchMap 比 mergeMap 更简单/更小。
    • 你摇滚!最后的更新真的很干净,很容易理解。对于诊断,它确实非常有帮助。但是,对于在最后一步使用,我是否仍应使用此方法并通过使用 next 值检查 complete 部分中的值来进行必要的控制?如果是这样,我可以创建一个块并在其中执行另一个 http 调用吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-04-01
    • 1970-01-01
    • 2018-04-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多