fetch需手动实现重试,仅对可恢复异常(如网络中断、5xx、429)重试,避免重试4xx客户端错误;采用指数退避+抖动控制节奏,并配合abortcontroller设置超时。

Fetch 本身不带重试能力,网络异常(比如断网、DNS失败、连接被重置)会直接抛出 TypeError: Failed to fetch,这类错误需要你手动捕获并决定是否重试。关键不是“一律重试”,而是识别哪些异常可恢复、何时重试、怎么避免雪崩。
只对可恢复的网络异常重试
不是所有失败都该重试。真正适合重试的,是那些大概率短暂、服务端无状态、重试后可能成功的场景:
-
网络中断类:如
TypeError: Failed to fetch(常见于离线、防火墙拦截、跨域失败等) -
连接异常类:如 Node.js 中的
ECONNRESET、ENOTFOUND、ETIMEDOUT -
5xx 服务端临时错误:如
502 Bad Gateway、503 Service Unavailable、504 Gateway Timeout -
限流响应:
429 Too Many Requests,尤其配合Retry-After响应头时
而 400、401、403、404 这类客户端错误,重试不会改变结果,应直接返回或提示用户。
用指数退避控制重试节奏
连续重试不仅浪费资源,还可能压垮后端。推荐使用指数退避(Exponential Backoff),每次失败后等待时间翻倍,并加入随机抖动防“重试风暴”:
- 第 1 次失败后等 1 秒
- 第 2 次失败后等 2–3 秒(1×2 + 0–1s 抖动)
- 第 3 次失败后等 4–6 秒(2×2 + 0–2s 抖动)
代码中可用 Math.pow(2, attempt) * 1000 + Math.random() * 1000 实现。
必须搭配超时与 AbortController
原生 fetch 没有超时机制,一次卡住可能让整个重试逻辑挂起。应在每次 fetch 调用中注入 AbortController:
- 创建
const controller = new AbortController() - 将
signal: controller.signal传入 fetch options - 设置定时器,比如
setTimeout(() => controller.abort(), 8000) - 捕获
AbortError或TypeError(被中止时),视为可重试异常
封装一个可靠的基础重试函数
把上述逻辑收拢成一个可复用的函数,支持传入 URL、选项、最大重试次数和超时时间:
示例核心逻辑(简化版):
async function fetchWithRetry(url, options = {}, { retries = 3, timeout = 8000 } = {}) {
for (let i = 0; i controller.abort(), timeout);
<pre class="brush:php;toolbar:false;">try {
const res = await fetch(url, { ...options, signal: controller.signal });
clearTimeout(timeoutId);
if (res.ok) return res;
if (res.status >= 500 || res.status === 429) {
if (i setTimeout(r, delay));
}} }
调用时:fetchWithRetry('/api/data', { method: 'POST' }, { retries: 2, timeout: 5000 })
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











