JavaScript异步重试器核心是将shouldRetry升级为返回Promise的函数,支持await判断是否重试,配合最大重试次数、延迟策略及错误透传机制,确保流程可控可配置。

JavaScript 中实现支持异步判断条件的重试器,核心在于把“是否重试”的决策逻辑从同步布尔值升级为可等待的 Promise,同时保持重试流程可控、可配置。
重试器需支持异步终止条件
传统重试常基于固定次数或同步错误判断(如 err instanceof NetworkError),但真实场景中,是否重试可能依赖异步操作:比如检查 token 是否已刷新成功、轮询后端状态接口返回是否就绪、或调用权限服务确认当前用户是否有重试资格。这时不能直接用 if (shouldRetry()),而要写成 if (await shouldRetry())。
关键设计点:
- 重试判定函数
shouldRetry类型应为(error: any, attempt: number) => Promise<boolean></boolean> - 每次尝试失败后,先 await 判定结果,为 true 才继续下一次;为 false 或抛错则终止并抛出最终错误
- 需设最大重试次数和延迟策略,避免无限等待
基础异步重试器实现(无第三方库)
以下是一个轻量、可复用的重试函数示例:
立即学习“Java免费学习笔记(深入)”;
async function retryAsync<T>(
fn: () => Promise<T>,
options: {
maxRetries?: number;
delayMs?: number | ((attempt: number) => number);
shouldRetry?: (error: any, attempt: number) => Promise<boolean>;
} = {}
) {
const { maxRetries = 3, delayMs = 1000 } = options;
const shouldRetryFn = options.shouldRetry ?? (() => Promise.resolve(true));
for (let i = 0; i <= maxRetries; i++) {
try {
return await fn();
} catch (err) {
if (i === maxRetries) throw err;
const should = await shouldRetryFn(err, i + 1);
if (!should) throw err;
const delay = typeof delayMs === 'function' ? delayMs(i + 1) : delayMs;
await new Promise(r => setTimeout(r, delay));
}
}
}
使用示例:仅当 token 刷新成功后才重试请求
const response = await retryAsync(
() => fetch('/api/data'),
{
maxRetries: 2,
delayMs: 500,
shouldRetry: async (err, attempt) => {
if (err?.status === 401 && attempt === 1) {
await refreshToken(); // 异步刷新
return true;
}
return false;
}
}
);
组合多个异步条件与短路逻辑
实际中 may 需要多个异步校验(如:token 有效 + 配额未超 + 维护窗口已过)。建议将它们封装为一个返回 Promise<boolean></boolean> 的组合函数,内部用 Promise.all 或串行 await 控制顺序与短路:
- 用
await a() && await b() && await c()实现串行且短路(任一 false 就停) - 用
Promise.all([a(), b(), c()]).then(results => results.every(Boolean))并行但不短路,适合无依赖的独立检查 - 避免在
shouldRetry中做耗时操作,超时应主动 reject,防止重试卡死
注意错误透传与调试友好性
异步重试器容易掩盖原始错误堆栈。建议:
- 在 catch 块中保留原始 error 的 name/message,必要时添加重试上下文(如
err.retryContext = { attempt, timestamp }) - 对
shouldRetry自身抛错做兜底处理(例如 log 错误并默认不重试),避免因判定逻辑异常导致意外重试 - 可选增加
onRetry回调用于日志或监控:onRetry?.(err, attempt, delay)


















