【问题标题】:Angular 2 RxJS Observable: Retry except on 429 statusAngular 2 RxJS Observable:重试,除了 429 状态
【发布时间】:2026-02-05 08:35:01
【问题描述】:

我已经编写了我的 Observable(来自 HTTP 请求)以在失败时重试。但是,如果服务器返回 429 Too many requests 错误,我想重试。

无论如何,当前的实现都会重试两次,间隔 1 秒。

return this.http.get(url,options)
    .retryWhen(errors => {
        return errors.delay(1000).take(2);
    })
    .catch((res)=>this.handleError(res));

errors 是一个 Observable。如何获取导致错误的底层 Response 对象?有了它,我可以访问服务器的状态码,只有在不是 429 时才重试:

return this.http.get(url,options)
    .retryWhen(errors => {
        if($code == 429) throw errors;
        else return errors.delay(1000).take(2);
    })
.catch((res)=>this.handleError(res));

如何在retryWhen 中获取状态码?

Live demo on Plunker

Angular 2 rc.6RxJS 5 Beta 11Typescript 2.0.2

【问题讨论】:

  • 如果因为从服务器接收到错误而引发错误,则错误实例应包含statusstatusText 属性。
  • @cartant 是的,但我如何获得这个实例?如果我删除retryWhen,则实例将作为Response 类的对象传递给上面的handleError()。但我不知道如何在retryWhen 逻辑期间阅读它。正如我在 OP 中提到的,该函数接收的(上面称为 errors)是 Observable,而不是带有 statusstatusText 属性的 http Response
  • 我希望可观察到的错误(这是服务器错误的结果)中的任何错误实例都包含statusstatusText 属性。我不熟悉 retryWhen 运算符 - 因此是评论 - 但您应该能够从错误本身中获取 status
  • statusstatusText 属性在 HTTP 客户端的 error-handling 示例中被提及/暗示。
  • @cartant 请注意,这些内容在错误处理函数中可用。但是retryWhen 在不同的上下文中执行。让我把一个plunker放在一起,这样我们就可以具体了。

标签: angular typescript observable rxjs5


【解决方案1】:

您可以将 429 错误的处理组合到传递给 retryWhenerrors observable 中。 errors observable 发出的错误如果是从服务器接收到的错误,则将包含 status 属性。

如果您不想在发生 429 错误时重试,而是希望抛出错误,您可以执行以下操作:

return this.http.get(url,options)
    .retryWhen((errors) => {
        return errors
            .mergeMap((error) => (error.status === 429) ? Observable.throw(error) : Observable.of(error))
            .delay(1000)
            .take(2);
    })
    .catch((res) => this.handleError(res));

如果您希望 HTTP observable 在不发出错误或响应的情况下完成,您可以简单地过滤 429 错误。

【讨论】:

  • 酷。我回来分享我的解决方案(我使用了switchMap),但这也有效。 plnkr.co/edit/iz9N8LzYIghwqqrstNEN?p=preview 。感谢卡特
  • 只是要注意一些可能很明显的事情,在这浪费了几个小时之后。 retryWhen 必须在 catch 之前!如果它在之后,它会被调用但有空错误主题并且您无法在响应中检查状态、消息等。