【问题标题】:RxJs zip operator, check which one throws an error and continue on condition?RxJs zip 运算符,检查哪个抛出错误并在条件下继续?
【发布时间】:2022-01-03 17:56:59
【问题描述】:

我将 2 个 api 服务调用压缩到一个 observable 中:

const firstAPIrequest = this.firstApi.getData();
const secondAPIrequest = this.secondApi.getData();

const combined = zip(firstAPIrequest, secondAPIrequest);

我目前映射这些以返回一个数组:

combined.pipe(
   map((res) => {
      return [res[0], res[1]) // just an example
   }
);

然后我将它用作不同组件中的订阅

combined.subscribe(
   (res) => this.handleData(res),
   (err) => {
      console.debug('Fetch failed', err);
   }
)

在这种情况下,如果其中一个 API 请求失败,它会显示错误,但我想检查其中一个失败,例如;如果request1 返回数据并且request2 失败,我仍然会从request1 返回数据

我尝试过catchError,但我认为我无法获取此函数中的数据

combined.pipe(
   catchError((err) => ...), // how would I catch the data before it throws an error?
   map((res) => {
      return [res[0], res[1]) // just an example
   }
);

【问题讨论】:

  • 您希望处理错误还是完全忽略它们?
  • @MichaelD 不要完全忽略它们,而是如果两者都失败抛出错误,如果只有一个失败而另一个工作它不应该抛出

标签: angular error-handling rxjs observable rxjs6


【解决方案1】:

您必须在两个来源上都捕获错误,因为如果您在组合后捕获错误,则组合流会在第一个错误后停止。例如:

const replaceErrorWithNull = catchError(() => of(null));

const firstAPIrequest = this.firstApi.getData();
const secondAPIrequest = this.secondApi.getData();

const combined = zip(
  firstAPIrequest.pipe(replaceErrorWithNull), 
  secondAPIrequest.pipe(replaceErrorWithNull)
);

使用这种方法,null 将代替 API 中出错的数据

【讨论】:

  • 谢谢,所以我不能只检查其中一个是否失败?
  • 如果我的问题是正确的,那么使用这段代码,如果第一个 API 失败而第二个没问题,您将得到 [null, {...data}]
【解决方案2】:

要单独处理来自每个源的错误,catchError 必须单独通过管道传递到每个源。 catchError 必须返回一个 observable,所以我们将使用 RxJS of 函数。

import { of, catchError } from 'rxjs';

const handleError = (error: any) => of({error: error});

const firstAPIrequest = this.firstApi.getData().pipe(
  catchError(this.handleError)
);
const secondAPIrequest = this.secondApi.getData().pipe(
  catchError(this.handleError)
);

const combined = zip(firstAPIrequest, secondAPIrequest);

现在在订阅中,您可以检查响应是有效还是错误。

combined.subscribe(
  ([res1, res2]) => {
    if (!!res1.error && !!res2.error) {
      // both API calls threw error
    } else if (!!res1.error) {
      // `firstAPIrequest` threw error
    } else if (!!res2.error) {
      // `secondAPIrequest` threw error
    } else {
      // both returned responses
    }
  }
);

注意:这假定实际响应不包含属性error。如果是这样,请将 handleError 函数中的 error 属性替换为其他内容。

【讨论】:

  • 非常感谢,但它仍然在 subscribe() 中抛出错误,错误被附加到对象但我无法订阅忽略默认错误
  • 我不太明白。确切的预期行为是什么?在当前的实现中,订阅的error 回调永远不会被触发,因为使用of 函数将错误转换为next 排放。
猜你喜欢
  • 2021-12-27
  • 1970-01-01
  • 2021-07-29
  • 2021-09-11
  • 1970-01-01
  • 2017-08-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多