【问题标题】:Rxjs - How to retry an errored observable while informing UI of the errorRxjs - 如何在通知 UI 错误时重试错误的 observable
【发布时间】:2019-09-08 16:23:34
【问题描述】:

问题

假设有一个 Http 请求 observable 出错了,我们可以重试它。但我也希望 UI 通知用户该资源无法加载。最好的架构是什么?

目标 Observable 的预期行为

  1. 可重试。
  2. 长时间运行。未完成或出错。
  3. 共享。多个订阅者时不会产生不必要的请求。
  4. 按需加载。未订阅时不会产生不必要的请求。
  5. 将错误通知 UI。

(3和4可以通过shareReplay({bufferSize: 1, refCount: true})实现)

我的尝试

我认为最好将错误消息传递给下游观察者,同时继续重试源。它会对架构造成最小的更改。但是我没有看到可以用 Rxjs 做到这一点的方法,因为

  1. retry() 总是拦截错误。如果您实现了错误,那么retry() 将不会重试。如果不是,则不会有错误传播到下游。
  2. catchError() 不重新抛出将始终完成流。

虽然让UI观察者tap(,,onError)retry()可以满足这个需求,但是我觉得让UI来承担这个责任是很危险的。并且多个 UI 观察者意味着很多重复的重试。

【问题讨论】:

    标签: rxjs rxjs6 reactivex data-layers


    【解决方案1】:

    好吧,我似乎在浏览文档时无意中找到了答案。

    首先使用catchError 的第二个参数。根据文档,retry 是由catchError 实现的。并且我们可以用更底层的catchError来表达更多的逻辑。

    原来如此

    catchError((err, caught) => {
      return timer(RETRY_DELAY_TIME).pipe(
        mergeMap(() => caught)
        startWith(err)
      );
    })
    

    它重试可观察对象,同时向下游观察者发送错误消息。所以下游知道连接错误,并且可以期望接收重试值。

    【讨论】:

    • 此代码将等待整个 RETRY_DELAY_TIME,然后再向订阅者发出错误。在我的情况下是 20 秒,因此在用户收到任何错误通知之前有很长的延迟,我们打算重试。这是一个对我有用的替代方案(非常感谢 First_Strike 首先向我展示了如何做到这一点):catchError((err, caught) => { return concat( of(err), timer(RETRY_DELAY_TIME).pipe(mergeMap(() => caught)) ); })
    【解决方案2】:

    听起来您正在寻找类似于 NgRx 副作用的东西。您可以将所有内容封装在外部 Observable 中,将错误处理程序通过管道传递到内部 Observable(您的 HTTP 调用),如下所示:

    const myObs$ = fromEvent('place event that triggers call here').pipe(
                   // just one example, you can trigger this as you please
      switchMap(() => this.myHttpService.getResource().pipe(
        catchError(err => handleAndRethrowError()),
        retry(3)
      ),
      shareReplay()
    );
    

    这样,如果请求抛出错误,它会重试 3 次(在 catchError 块中进行错误处理,即使它完全出错,外部 Observable 仍然是活动的。看起来像这样吗?有意义吗?

    【讨论】:

    • 如果我想分离 UI 和数据基础设施,我可以将在您的 handleAndRethrowError() 中捕获的错误消息发送到 Subject 并让 UI 订阅 Subject。这是您想要的解决方案吗?
    • 这是一种做事方式,是的。基本上你可以在catchError 块中做任何你喜欢的错误处理。
    • 谢谢。如果有更好的架构(我仍然觉得我的解决方案很笨拙),请告诉我。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-08-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多