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})) );
代码解释
retryWhen:不像retry那样无脑重试,它允许我们自定义重试的触发条件scan操作符:一方面计数重试次数,另一方面判断错误类型——只有当错误是ErrorEvent(通信错误)且重试次数未达3次时,才会继续重试;否则直接抛出错误delay:可选但推荐,给重试添加间隔,避免短时间内多次请求导致的问题
结合你的拦截器的兼容性
你的认证拦截器会捕获401/403错误并做相应处理,这些错误属于服务器端错误,会被scan里的判断逻辑直接抛出,不会进入重试流程,完全符合你的需求。
额外优化:更严谨的错误判断
如果你遇到某些特殊场景(比如部分代理返回的网络错误status不是0),可以把判断条件改成更严谨的组合:
if (!(err.error instanceof ErrorEvent) && err.status !== 0) { throw err; }
这样就能确保只有真正的通信错误才会触发重试,其他错误直接进入错误处理流程啦~
内容的提问来源于stack exchange,提问作者luca
相关产品推荐
相关产品推荐

