Angular - 链接 Observables 并合并它们的结果

Angular - chaining Observables and combining their results

我想运行按顺序执行以下2个请求,最后合并它们的结果。

  1. 如果第一个请求的响应主体包含isSuccessful = false,那么第二个不应该运行。
  2. 如果第一个请求因任何原因失败,第二个请求不应运行。
  3. 如果第二个请求失败,应该不会影响第一个。 combineAndPrintMsg() 应该只对第一个请求的响应消息成功工作。

我试过如下所示的嵌套订阅,但我听说这不是一个好方法。

firstReq = this.http.get("https://myApi.com/posts?userId=1");
secondReq = this.http.get("https://myApi.com/albums?userId=1");

.....

this.firstReq.subscribe(res1 => {
  const secondReqResult = this.doSecondRequest(res1);
  this.combineAndPrintMsg(res1, secondReqResult)
})

.....

doSecondRequest(res1: any) {
  let secondReqResponse;
  if (res1.isSuccessful) {
    this.secondReq.subscribe(res2 => {
      secondReqResponse = res2;
    })
    return secondReqResponse;
  }
}

combineAndPrintMsg(res1, res2) {
  console.log(res1.message + res2.message || '');
}

每个人在开始使用 rxjs 时需要知道的第一件事是不要在 observable 中订阅 observable。 (我过去也一直这样做)。有些运算符可以合并您应该学习的可观察对象的输出。

在这种情况下,我将在管道内使用 switchMap 让第一个 observable 执行第二个 if 第一个结果的 isSuccessful 为真。然后,我将两个结果合并到第二个请求的管道中——除非出现错误。如果是,则使用 catchError 以便仅返回第一个结果。

firstReq = this.http.get("https://myApi.com/posts?userId=1");
secondReq = this.http.get("https://myApi.com/albums?userId=1");

this.firstReq.pipe(
  switchMap((res1) => res1.isSuccessful 
    ? this.secondReq.pipe(
      map((res2) => ({ res1, res2 })), 
      catchError(() => of({ res1, res2: undefined }))
    )
    : of({ res1, res2: undefined })
  ),
  tap(({ res1, res2 }) => this.combineAndPrintMsg(res1, res2))
);

combineAndPrintMsg(res1, res2) {
  console.log(`${res1.message}${res2?.message}`);
}

switchMap的选择是任意的,你应该了解它与concatMapmergeMap[=之间的区别24=].