You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Angular中仅针对客户端/网络错误重试HTTP请求的实现问题

嗨,我完全懂你的痛点——默认的retry(3)不管什么错误都重试三次,像401未授权、403禁止访问这种服务器端错误,重试根本没用,反而还会在控制台刷一堆没必要的日志。下面我来给你实现只针对网络中断/客户端通信错误的重试逻辑,解决你的编译错误问题:

核心判断逻辑

Angular的HttpErrorResponse里,两种错误的区分方式很明确:

  • 网络/客户端通信错误:比如断网、连接超时,此时err.error是ErrorEvent实例,且err.status通常为0
  • 服务器端错误:比如4xx、5xx状态码,此时err.error是服务器返回的具体内容(比如JSON、字符串),不是ErrorEvent

替换retry(3)为retryWhen的正确实现

首先要确保导入所需的RxJS操作符(这很可能是你之前出现编译错误的原因):

import { retryWhen, scan, delay, throwError } from 'rxjs/operators';

然后修改你的HTTP请求代码:

return this.http.get<ApiResult<Atto[]>>(this.apiEnv + "Atti")
  .pipe(
    retryWhen(errors => 
      errors.pipe(
        // 扫描重试次数,同时判断错误类型
        scan((retryCount, err: HttpErrorResponse) => {
          // 重试次数达到3次,直接抛出错误进入catchError
          if (retryCount >= 3) {
            throw err;
          }
          // 非通信错误(服务器端错误),直接抛出不重试
          if (!(err.error instanceof ErrorEvent)) {
            throw err;
          }
          // 符合重试条件,计数+1
          return retryCount + 1;
        }, 0),
        // 可选:每次重试前延迟1秒,避免频繁请求给服务器施压
        delay(1000)
      )
    ),
    catchError(err => this.handleError.handleError(err, {severity:'error', summary:'Impossibile recuperare gli atti', life:5000}))
  );

代码解释

  1. retryWhen:不像retry那样无脑重试,它允许我们自定义重试的触发条件
  2. scan操作符:一方面计数重试次数,另一方面判断错误类型——只有当错误是ErrorEvent(通信错误)且重试次数未达3次时,才会继续重试;否则直接抛出错误
  3. delay:可选但推荐,给重试添加间隔,避免短时间内多次请求导致的问题

结合你的拦截器的兼容性

你的认证拦截器会捕获401/403错误并做相应处理,这些错误属于服务器端错误,会被scan里的判断逻辑直接抛出,不会进入重试流程,完全符合你的需求。

额外优化:更严谨的错误判断

如果你遇到某些特殊场景(比如部分代理返回的网络错误status不是0),可以把判断条件改成更严谨的组合:

if (!(err.error instanceof ErrorEvent) && err.status !== 0) {
  throw err;
}

这样就能确保只有真正的通信错误才会触发重试,其他错误直接进入错误处理流程啦~

内容的提问来源于stack exchange,提问作者luca

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.12 04:14:07