async/await实现请求自动重试的核心是封装retry函数,支持次数限制、延迟等待、智能错误判断、指数退避及AbortController超时控制。

在网络不稳时,用 async/await 实现请求自动重试,核心是封装一个带重试逻辑的异步函数,捕获失败(如网络超时、502、408 等),并在一定次数内重复发起请求,同时加入延迟避免雪崩。
基础重试函数:支持次数限制与间隔等待
写一个通用的 retry 工具函数,接收原始异步操作、最大重试次数和每次失败后的等待毫秒数:
async function retry(fn, options = {}) {
const { maxRetries = 3, delay = 1000 } = options;
<p>for (let i = 0; i <= maxRetries; i++) {
try {
return await fn(); // 成功则直接返回结果
} catch (err) {
if (i === maxRetries) throw err; // 最后一次失败,抛出最终错误
await new Promise(resolve => setTimeout(resolve, delay));
}
}
}使用示例:
const fetchData = async () => {
const res = await fetch('/api/data');
if (!res.ok) throw new Error(`HTTP ${res.status}`);
return res.json();
};
<p>// 自动最多重试 3 次,每次间隔 1 秒
try {
const data = await retry(fetchData, { maxRetries: 3, delay: 1000 });
console.log(data);
} catch (err) {
console.error('请求最终失败:', err.message);
}智能重试:只对特定错误类型重试
不是所有错误都该重试(比如 401 或 404)。可扩展 retry,增加 shouldRetry 判断函数:
立即学习“Java免费学习笔记(深入)”;
Java项目代码review工具。分析Git变更+完整调用链路上下文,推断业务需求,进行多维度评分和分类汇总,生成完整PRD文档。包含细粒度Java代码审查清单(Null安全、异常处理、Streams、并发、equals/hashCode、资源管理、API设计、性能、MyBatis/ORM、事务边界、SQL/DD...
async function retry(fn, options = {}) {
const {
maxRetries = 3,
delay = 1000,
shouldRetry = (err) => /network|timeout|50[0-4]|408/.test(err.message)
} = options;
<p>for (let i = 0; i <= maxRetries; i++) {
try {
return await fn();
} catch (err) {
if (i === maxRetries || !shouldRetry(err)) throw err;
await new Promise(resolve => setTimeout(resolve, delay));
}
}
}这样就能跳过身份过期(401)、资源不存在(404)等无需重试的错误,只对网络中断、超时、服务端临时错误(500–504)、客户端超时(408)等重试。
指数退避:避免重试风暴
连续快速重试可能加重服务器压力或触发限流。改用指数退避(每次等待时间翻倍)更稳妥:
async function retry(fn, options = {}) {
const { maxRetries = 3, baseDelay = 500 } = options;
<p>for (let i = 0; i <= maxRetries; i++) {
try {
return await fn();
} catch (err) {
if (i === maxRetries) throw err;
// 第 0 次失败后等 500ms,第 1 次后等 1000ms,第 2 次后等 2000ms...
const delay = baseDelay * Math.pow(2, i);
await new Promise(resolve => setTimeout(resolve, delay));
}
}
}结合 AbortController 控制单次请求超时
原生 fetch 不支持超时,但可用 AbortController 配合 Promise.race 实现单次请求限时,防止卡死:
function timeoutFetch(url, options = {}, ms = 8000) {
const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), ms);
<p>return Promise.race([
fetch(url, { ...options, signal: controller.signal })
.finally(() => clearTimeout(timeoutId)),
new Promise((_, reject) =>
setTimeout(() => reject(new Error('Request timeout')), ms)
)
]);
}</p><p>// 使用时传入带超时的 fetch 封装
const fetchData = () => timeoutFetch('/api/data', {}, 5000);
await retry(fetchData, { maxRetries: 2, baseDelay: 300 });这样每轮重试里,单次请求最多等 5 秒,超时即报错并触发下一轮重试。

















