promise 本身不内置重试与退避机制,但可通过封装 promise 链+指数退避逻辑实现带自动重试、延迟退避的异步任务控制,核心是递归/循环封装 retry 函数,按错误类型、重试次数和动态延迟(如100ms、200ms、400ms)决定重试或最终抛错。

Promise 本身不内置重试与退避机制,但可以通过封装 Promise 链 + 指数退避逻辑,实现带自动重试、延迟退避的异步任务控制。
核心思路:用递归或循环封装 retry 逻辑
把原始异步操作(如 fetch)包装成一个返回 Promise 的函数,失败时不直接 reject,而是根据重试次数决定:立即重试、等待后重试,或最终抛出错误。
- 每次失败后计算下一次延迟时间(例如:100ms, 200ms, 400ms… 即指数增长)
- 限制最大重试次数,避免无限循环
- 可选:对特定错误码(如网络超时、503)才重试,跳过 400 类客户端错误
基础重试 + 线性退避示例
适合简单场景,每次固定延时:
function retry(fn, maxRetries = 3, delayMs = 1000) {
return fn().catch(err => {
if (maxRetries setTimeout(resolve, delayMs))
.then(() => retry(fn, maxRetries - 1, delayMs));
});
}
<p>// 使用
retry(() => fetch('/api/data'), 3, 1000)
.then(res => res.json())
.catch(err => console.error('彻底失败:', err));
</p>
推荐:指数退避 + 错误过滤
更健壮的做法,区分错误类型,并让延迟随重试次数增长:
Java项目代码review工具。分析Git变更+完整调用链路上下文,推断业务需求,进行多维度评分和分类汇总,生成完整PRD文档。包含细粒度Java代码审查清单(Null安全、异常处理、Streams、并发、equals/hashCode、资源管理、API设计、性能、MyBatis/ORM、事务边界、SQL/DD...
function retryWithBackoff(fn, options = {}) {
const {
maxRetries = 3,
baseDelay = 100,
maxDelay = 3000,
shouldRetry = (err) => err?.name === 'TypeError' || err?.status >= 500
} = options;
<p>function attempt(retryCount = 0) {
return fn().catch(err => {
if (retryCount >= maxRetries || !shouldRetry(err)) throw err;</p><pre class="brush:php;toolbar:false;"><pre class="brush:php;toolbar:false;"> const delay = Math.min(baseDelay * Math.pow(2, retryCount), maxDelay);
return new Promise(resolve => setTimeout(resolve, delay))
.then(() => attempt(retryCount + 1));
});}
return attempt(); }
// 使用:只对网络错误或服务端错误重试
retryWithBackoff(
() => fetch('/api/order').then(r => {
if (!r.ok) throw new Error(HTTP ${r.status}
搭配 async/await 写法更清晰
避免嵌套,逻辑更易读:
async function fetchWithRetry(url, options = {}) {
const { maxRetries = 3, baseDelay = 100 } = options;
<p>for (let i = 0; i = 500 && i setTimeout(r, baseDelay <em> Math.pow(2, i)));
continue;
}
throw new Error(<code>HTTP ${res.status}</code>);
} catch (err) {
if (i === maxRetries) throw err;
await new Promise(r => setTimeout(r, baseDelay </em> Math.pow(2, i)));
}
}
}
</p>
不复杂但容易忽略:退避不是越长越好,要结合业务容忍度;重试前最好记录日志或上报,方便排查是否频繁触发;前端重试不宜替代后端幂等设计。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










