Fetch 本身不提供重试功能,需手动封装:捕获网络错误或5xx状态码等临时性失败,结合指数退避、AbortController超时控制及重试次数限制实现健壮请求。

Fetch 本身不提供重试功能,需要手动封装逻辑来实现失败后的自动重试。核心思路是:捕获网络错误或非成功状态码,延迟后重新发起请求,控制重试次数和间隔避免雪崩。
判断哪些错误需要重试
不是所有失败都适合重试。通常只对临时性问题重试,比如网络中断、500/502/503 等服务端临时错误;而 400、401、404 这类客户端错误一般不重试。
- 网络异常(如
TypeError: Failed to fetch)——可重试 - 响应状态码为 5xx(服务器内部错误)——可重试
- 响应状态码为 4xx(除 408、429 外多数是客户端问题)——通常不重试
- 超时(需配合 AbortController 实现)——可重试
基础重试函数封装
用 async/await 封装一个支持重试的 fetch 函数,传入 URL、选项和最大重试次数:
async function fetchWithRetry(url, options = {}, retries = 3) {
for (let i = 0; i <= retries; i++) {
try {
const res = await fetch(url, options);
// 成功响应且状态码在 200–299 范围内才返回
if (res.ok) return res;
// 非 2xx 且是 5xx 错误,且不是最后一次尝试,则抛出错误触发重试
if (res.status >= 500 && res.status < 600 && i < retries) {
throw new Error(`HTTP ${res.status}`);
}
return res; // 其他状态码(如 404)直接返回,不重试
} catch (err) {
if (i === retries) throw err;
// 指数退避:第一次等 1s,第二次等 2s,第三次等 4s...
await new Promise(r => setTimeout(r, Math.pow(2, i) * 1000));
}
}
}添加超时与 AbortController 支持
原生 fetch 没有超时机制,容易卡住。结合 AbortController 可主动中断请求,避免无限等待:
立即学习“Java免费学习笔记(深入)”;
- 创建
AbortController实例,将signal传入 fetch 选项 - 设置定时器,在指定毫秒后调用
controller.abort() - 捕获
AbortError或TypeError(被中止时抛出)并重试
示例中可在 options 里加 timeout: 5000,并在函数内处理超时逻辑。
实际使用示例
调用时像普通 fetch 一样,但自带重试能力:
fetchWithRetry('/api/data', { method: 'POST', body: JSON.stringify({x:1}) }, 2)
.then(res => res.json())
.then(data => console.log(data))
.catch(err => console.error('最终失败:', err));上面代码最多尝试 3 次(初始 + 2 次重试),失败后按指数退避等待,最终抛出最后一次错误。


















