Promise本身不内置重试逻辑,但可通过async/await循环、Promise递归或高阶函数withRetry实现可控重试,支持指数退避、错误码判断与配置化扩展。

Promise 本身不内置重试逻辑,但可以通过封装 Promise 链或使用 async/await 配合循环来实现可控的重试机制。关键在于捕获失败、判断是否重试、延迟后重新发起请求,并限制最大重试次数。
用 async/await + while 循环实现基础重试
这是最直观、易理解的方式,适合需要精细控制重试条件(如只对特定错误码重试)的场景:
async function fetchWithRetry(url, options = {}, maxRetries = 3) {
let lastError;
let attempt = 0;
<p>while (attempt <= maxRetries) {
try {
const response = await fetch(url, options);
if (!response.ok) {
throw new Error(<code>HTTP ${response.status}: ${response.statusText}</code>);
}
return await response.json();
} catch (err) {
lastError = err;
attempt++;
if (attempt <= maxRetries) {
// 指数退避:100ms, 200ms, 400ms...
await new Promise(resolve => setTimeout(resolve, Math.pow(2, attempt - 1) * 100));
}
}
}</p><p>throw lastError; // 超过重试次数后抛出最终错误
}✅ 优点:逻辑清晰、可读性强、支持动态判断(比如只对 500 错误重试,跳过 404)
❌ 注意:不要在生产中直接用 fetch 的原始响应做业务判断,建议统一处理 status 和 error 类型。
用 Promise 链递归实现(无 async/await)
适用于需兼容旧环境,或偏好函数式风格的场景:
function fetchWithRetry(url, options = {}, maxRetries = 3, delay = 100) {
return fetch(url, options)
.then(response => {
if (!response.ok) {
throw new Error(`HTTP ${response.status}`);
}
return response.json();
})
.catch(err => {
if (maxRetries <= 0) throw err;
return new Promise(resolve =>
setTimeout(() => resolve(), delay)
).then(() =>
fetchWithRetry(url, options, maxRetries - 1, delay * 2)
);
});
}⚠️ 注意:这里用了指数退避(delay * 2),避免服务雪崩;递归深度受重试次数限制,不会栈溢出。
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
立即学习“Java免费学习笔记(深入)”;
封装成可复用的高阶函数(推荐)
把重试逻辑抽象为工具函数,让任何 Promise 创建函数都能“插拔式”支持重试:
function withRetry(fn, { maxRetries = 3, baseDelay = 100, shouldRetry = () => true } = {}) {
return function(...args) {
const attempt = (n) => fn(...args).catch(err => {
if (n <= 0 || !shouldRetry(err)) throw err;
return new Promise(r => setTimeout(r, baseDelay * Math.pow(2, maxRetries - n)))
.then(() => attempt(n - 1));
});
return attempt(maxRetries);
};
}
<p>// 使用示例:
const safeFetch = withRetry(fetch, {
maxRetries: 2,
shouldRetry: err => err.name === 'TypeError' || err.status >= 500
});
✅ 这样写解耦了重试策略和业务逻辑,便于测试、复用和配置化。
? 提示:shouldRetry 可根据 error 实例类型、status、message 正则等灵活定制。
配合 Axios 等库的实践建议
Axios 原生不支持重试,但可通过拦截器或封装 request 方法实现:
- 在
response interceptor中对 5xx 状态码返回 rejected Promise,触发重试逻辑 - 利用
axios-retry第三方库(轻量、配置丰富,支持自定义重试条件和延迟) - 避免在请求拦截器里直接重试——可能造成重复发送,应在响应失败后统一决策
例如用 axios-retry:
import axios from 'axios';
import axiosRetry from 'axios-retry';
<p>axiosRetry(axios, {
retries: 3,
retryDelay: axiosRetry.exponentialDelay,
retryCondition: (error) => error.response?.status >= 500
});

















