示例说明
retry 包提供的是操作级重试原语而不是 HTTP 专用封装,适合包任意可能失败的异步动作。operation 对象维护尝试次数与退避节奏,retry 方法既是谓词也是执行器——返回 true 表示已安排下次尝试。randomize 给退避加入随机因子,防止多个客户端同步重试形成惊群。
技术要点
- factor 与 min/maxTimeout 构成指数退避区间
- randomize 打散多客户端同步重试
- mainError 返回最后一次失败供上层判断
代码解读
fetchWithRetry 把 operation 包进 Promise,attempt 回调里执行真正的请求:5xx 被转换为错误参与重试判定,成功则 resolve。catch 分支调用 operation.retry(err),不可重试或次数耗尽时返回 false,此时用 mainError 拒绝 Promise,把最后一次的真实错误交给调用方。
使用建议
signal 透传让调用方可以随时取消整个重试链。minTimeout 不要低于下游的恢复周期,否则前几次尝试必然失败。把可重试错误类型收敛成白名单谓词,避免对逻辑错误做无谓重试。
代码示例
import retry from 'retry';
async function fetchWithRetry(url, { signal } = {}) {
const operation = retry.operation({
retries: 5,
factor: 2,
minTimeout: 500,
maxTimeout: 8000,
randomize: true,
});
return new Promise((resolve, reject) => {
operation.attempt(async (currentAttempt) => {
try {
const res = await fetch(url, { signal });
if (res.status >= 500) throw new Error('upstream ' + res.status);
resolve(await res.json());
} catch (err) {
if (operation.retry(err)) return;
reject(operation.mainError());
}
});
});
}
const data = await fetchWithRetry('https://api.example.com/pricing');
console.log('plans:', data.plans.length);