在网络抖动场景下,需封装带指数退避、最大重试次数、abortcontroller 中断及幂等性校验的 retryfetch 函数,仅对网络类错误重试,保持 await 语义并支持业务降级。

在网络抖动场景下,单纯用 try-catch 捕获异常并不够——关键是要让失败的 await 请求有机会重试,且不卡住主线流程。核心思路是:把异步请求包装成可重试的 Promise,并在捕获到网络类错误(如 TypeError、AbortError 或状态码异常)时自动延迟重试,而非直接抛出。
封装带重试的 fetch 请求
不要每次写 await fetch(...) 都手动加 try-catch 和循环。统一封装一个 retryFetch 函数,内置指数退避和最大重试次数:
- 用
async/await+for...of控制重试次数,比递归更易读、不易栈溢出 - 每次失败后用
setTimeout延迟(如 100ms → 200ms → 400ms),避免雪崩式重试 - 只对明确的网络错误重试(如
TypeError: failed to fetch、AbortError、响应状态码 0 或 5xx),4xx 错误一般不重试
在业务层优雅集成重试逻辑
调用时保持语义清晰,不破坏原有 await 流程:
- 直接
const data = await retryFetch('/api/user'),像普通 await 一样使用 - 可选传入配置:重试次数(默认 3)、超时时间(默认 8s)、自定义判断是否重试的函数(比如只重试 GET 请求)
- 若最终仍失败,
retryFetch抛出最后一次错误,上层仍可用 try-catch 处理降级逻辑(如展示缓存数据或提示“稍后重试”)
配合 AbortController 实现可控中断
重试过程中用户可能已跳转或取消操作,需及时中止后续请求:
- 每次重试都新建
AbortController,并设置合理 timeout(如 5s) - 将
signal传给fetch,避免无效请求堆积 - 外部可通过同一个
AbortController主动取消整个重试链(比如组件卸载时调用abort())
避免常见陷阱
重试不是万能解药,需注意边界:
- 幂等性:确保重试的请求是安全的(GET、HEAD、幂等的 PUT/DELETE),非幂等 POST 不宜自动重试
- 状态污染:重试前清空可能影响下次请求的临时状态(如 token 过期需先刷新)
- 日志与监控:记录重试次数和最终结果,便于定位真实网络问题,而非掩盖它
不复杂但容易忽略:真正的自愈能力不在于多试几次,而在于试得有策略、停得有依据、错得有反馈。











