async函数本身无内置重试逻辑,需通过高阶函数封装;基础实现用for循环+await捕获异常并重试,支持最大重试次数与错误传播;进阶需结合AbortSignal实现超时取消,并区分可恢复错误与业务错误。

async 函数本身不内置重试逻辑,但可以借助高阶函数(装饰器模式)封装通用重试行为——核心是用 while 或递归 + await 控制重试次数与延迟,捕获异常后决定是否重试。
基础重试装饰器(固定次数 + 立即重试)
最简实现:接收原 async 函数、最大重试次数,出错就重试,成功则返回结果,失败则抛出最后一次错误。
function retry(fn, maxRetries = 3) {
return async function(...args) {
let lastError;
for (let i = 0; i <p>用法示例:</p><pre class="brush:php;toolbar:false;">const fetchWithRetry = retry(fetch, 2);
<p>// 调用时像普通 async 函数一样使用
try {
const res = await fetchWithRetry('<a href="https://www.php.cn/link/46b315dd44d174daf5617e22b3ac94ca">https://www.php.cn/link/46b315dd44d174daf5617e22b3ac94ca</a>');
console.log(await res.json());
} catch (err) {
console.error('请求失败,已重试 2 次', err);
}</p>带指数退避的重试装饰器(推荐生产使用)
避免瞬间密集重试压垮服务或触发限流,每次重试前等待时间按 2ⁿ 增长(如 100ms → 200ms → 400ms),并加入随机抖动防“重试风暴”。
- 支持自定义 baseDelay(基础延迟毫秒)、maxDelay(最大延迟)、jitter(抖动范围)
- 重试前用
setTimeout+Promise实现等待 - 仍保留最大重试次数控制
function retryWithBackoff(fn, options = {}) {
const {
maxRetries = 3,
baseDelay = 100,
maxDelay = 3000,
jitter = 0.2 // ±20% 抖动
} = options;
<p>return async function(...args) {
let lastError;
for (let i = 0; i </p><pre class="brush:php;toolbar:false;"> const delay = Math.min(baseDelay * Math.pow(2, i), maxDelay);
const jitterMs = delay * (Math.random() - 0.5) * 2 * jitter;
const actualDelay = Math.max(0, Math.round(delay + jitterMs));
await new Promise(r => setTimeout(r, actualDelay));
}
}
throw lastError;}; }
可配置条件的重试(按错误类型/状态码判断)
不是所有错误都该重试(比如 401、404、400 通常不该重试,而网络中断、502、503 可以)。装饰器可接受一个 shouldRetry 函数做决策。
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
-
shouldRetry(error, attempt)返回 true 才重试 - 可检查
error.name、error.status(若 error 是 Response)、或自定义字段
function retryIf(fn, shouldRetry, options = {}) {
const { maxRetries = 3 } = options;
<p>return async function(...args) {
let lastError;
for (let i = 0; i </p><pre class="brush:php;toolbar:false;"> // 这里可加延迟(如调用上面的 backoff 逻辑)
if (i setTimeout(r, 100 * (i + 1)));
}
}
throw lastError;}; }
// 示例:只对网络错误和 5xx 响应重试 const fetchWithSmartRetry = retryIf( fetch, (err, attempt) => { // 网络错误(无 response) if (!err.response) return true; // 5xx 服务器错误 return err.response.status >= 500 && err.response.status
结合 AbortSignal 实现可取消的重试
用户主动取消请求(如页面跳转、输入变化)时,应中止所有待重试任务。装饰器可透传 AbortSignal 并在每次重试前检查 signal.aborted。
function retryCancelable(fn, options = {}) {
const { maxRetries = 3 } = options;
<p>return async function(...args) {
// 允许传入 signal(例如从外部 AbortController 获取)
const signal = args.at(-1)?.signal;
let lastError;</p><pre class="brush:php;toolbar:false;">for (let i = 0; i setTimeout(r, 100 * (i + 1)));
}
}
throw lastError;}; }
调用时传入 signal:
const controller = new AbortController();
setTimeout(() => controller.abort(), 5000); // 5 秒后自动取消
<p>await retryCancelable(fetch, { maxRetries: 2 })(
'<a href="https://www.php.cn/link/46b315dd44d174daf5617e22b3ac94ca">https://www.php.cn/link/46b315dd44d174daf5617e22b3ac94ca</a>',
{ signal: controller.signal }
);</p>
不复杂但容易忽略的是:重试逻辑必须明确区分“可恢复错误”和“业务错误”,否则可能掩盖真实问题或造成副作用(如重复下单)。装饰器只是工具,关键在重试策略的设计。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










