角度:捕获 rxjs 管道/合并映射序列中的错误

Dre*_*rew 4 rxjs angular

目前我的代码结构如下,并且运行良好:

// service:
getRequestA() { return this.http.get(someUrl) }
getRequestB(id) { return this.http.get(someUrl + id) }
getRequestC(id) { return this.http.get(someUrl + id) }
getAll() {
  return getRequestA()
    .pipe(
      mergeMap((resp) => {
        return this.getRequestB(resp.id)
      }),
      mergeMap((resp) => {
        return this.getRequestC(resp.id)
      })
    )
}
Run Code Online (Sandbox Code Playgroud)

这允许我在我的组件中执行此操作:

// component:
service.getAll().subscribe(resp => {
  // result of service.getRequestC()
}, error => {
  // error occurred in any 1 of the 3 http calls
});
Run Code Online (Sandbox Code Playgroud)

这很棒,因为我在触发下一个调用之前需要每个调用的结果,而且我只关心最终结果。但是,现在我希望知道 3 个 http 调用中具体哪一个失败了,以便向用户显示更好的错误。我已经尝试了很多东西,但无法弄清楚如何在服务中抛出自定义错误,然后我可以在组件中区分这些错误。在此先感谢您的任何建议!

car*_*ant 6

像这样的安排应该允许您标记并重新抛出任何错误:

const tagError = (tag, error) => {
  error.tag = tag;
  return error;
};

getAll() {
  return getRequestA().pipe(
    catchError(error => { throw tagError("A", error); }),
    mergeMap(resp => this.getRequestB(resp.id).pipe(
      catchError(error => { throw tagError("B", error); })
    )),
    mergeMap(resp => this.getRequestC(resp.id).pipe(
      catchError(error => { throw tagError("C", error); })
    ))
  );
}
Run Code Online (Sandbox Code Playgroud)

事实上,您可以更进一步,将tagError函数转换为可管道运算符:

const tagError = tag => catchError(error => {
  error.tag = tag;
  throw error;
});

getAll() {
  return getRequestA().pipe(
    tagError("A"),
    mergeMap(resp => this.getRequestB(resp.id).pipe(tagError("B"))),
    mergeMap(resp => this.getRequestC(resp.id).pipe(tagError("C")))
  );
}
Run Code Online (Sandbox Code Playgroud)