应封装条件重试的 fetch 函数,仅对白名单 url、get/head 方法及 0/502/503/504 状态码重试,配合指数退避+抖动与 abortcontroller,避免雪崩。

直接封装一个带条件重试的 fetch 函数,比引入大型库更轻量、可控,也更适合多数前端项目。关键不是“每次都重试”,而是“只在该重试的时候才重试”——比如网络中断、502/503/504 等临时性错误,且仅限 GET/HEAD 这类安全请求。
只对白名单接口和状态码重试
盲目重试所有失败请求反而会加重服务压力或引发副作用(如重复提交)。应明确哪些请求允许重试:
-
URL 匹配:用正则限定范围,例如
/^https?:\/\/api\.example\.com\//i或/\/v2\/data$/ -
状态码过滤:只重试
0(网络断连)、502、503、504;跳过401、404、422等客户端错误 -
请求方法限制:默认只对
GET和HEAD重试,避免 POST/PUT 的非幂等风险
加入指数退避 + 随机抖动
连续重试不加延迟,容易触发“重试风暴”,造成服务雪崩。推荐用 baseDelay × 2^attempt + jitter 计算等待时间:
- 第 1 次失败后等 500ms,第 2 次等约 1000–1100ms,第 3 次等约 2000–2100ms
- 加
Math.random() * 200抖动,让并发请求错开时间点 - 配合
AbortController防止上一轮请求未结束就发起下一轮
封装成可复用的 retryFetch 函数
以下是一个生产可用的轻量实现(TypeScript 友好,也兼容纯 JS):
function retryFetch(input, init = {}, options = {}) {
const {
maxRetries = 3,
baseDelay = 500,
whitelistUrls = [/^https?:\/\/[^/]+\/api\//i],
whitelistStatuses = [0, 502, 503, 504],
whitelistMethods = ['GET', 'HEAD']
} = options;
<p>const url = typeof input === 'string' ? input : input.url || '';
const method = (init.method || 'GET').toUpperCase();
const isWhitelisted =
whitelistUrls.some(p => p.test(url)) &&
whitelistMethods.includes(method);</p><p>const attempt = async (n) => {
try {
const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), 10000);</p><pre class="brush:php;toolbar:false;"> const res = await fetch(input, { ...init, signal: controller.signal });
clearTimeout(timeoutId);
if (res.ok) return res;
if (whitelistStatuses.includes(res.status)) {
throw new Error(`HTTP ${res.status}`);
}
return res; // 非白名单状态,不重试
} catch (err) {
if (n >= maxRetries || !isWhitelisted) throw err;
const delay = baseDelay * Math.pow(2, n) + Math.random() * 200;
await new Promise(resolve => setTimeout(resolve, delay));
return attempt(n + 1);
}};
return attempt(0); }
调用方式与原生 fetch 一致:retryFetch('/api/users').then(r => r.json())。
搭配拦截器统一处理认证与日志
可在重试函数外再包一层拦截器,用于自动注入 token、记录失败 URL、上报监控等:
- 请求前:添加
Authorization头、打点埋点 - 响应后:对
401触发登录态刷新,429提取Retry-After并动态调整重试间隔 - 最终失败时:抛出结构化错误对象,含
url、status、attemptCount等字段,便于调试
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











