通过编写一个高阶函数,将原始 promise 包装在循环或递归逻辑中,并在捕获到特定错误时延迟执行重试,即可实现自动重试。具体做法是定义一个接受目标 promise、最大重试次数和重试间隔的函数,利用 try...catch 块拦截异常,若未达到上限则使用 settimeout 触发下一次调用,成功则直接返回结果。

如何封装支持自定义次数的重试逻辑
核心在于创建一个独立的辅助函数,该函数接收原始操作作为参数,并维护当前的重试计数。每次调用时,先尝试执行原始 Promise,如果成功则立即 resolve;如果失败且剩余次数大于零,则等待指定时间后再次调用自身。这种递归模式能确保只有当所有重试机会耗尽或操作成功时,外层调用才会结束。

function retryPromise(fn, maxRetries = 3, delay = 1000) {
return new Promise((resolve, reject) => {
let attempts = 0;
function execute() {
fn().then(resolve).catch(error => {
attempts++;
if (attempts <= maxRetries) {
console.log(`Retry ${attempts}/${maxRetries}`);
setTimeout(execute, delay);
} else {
reject(error);
}
});
}
execute();
});
}
// 模拟异步请求
const fetchResource = () => new Promise((res, rej) => {
Math.random() > 0.5 ? res('Success') : rej(new Error('Failed'));
});
retryPromise(fetchResource, 3, 1000)
.then(data => console.log('Final Result:', data))
.catch(err => console.error('All retries failed:', err));上述代码定义了一个通用的 retryPromise 函数。它内部维护了 attempts 计数器,并通过闭包引用外部的 maxRetries 和 delay 参数。当 fn() 抛出异常时,进入 catch 分支判断是否还有重试机会。如果有,则通过 setTimeout 调度下一次执行;如果没有,则拒绝最终的 Promise。测试部分模拟了一个随机失败的请求,观察控制台输出以验证重试机制是否按预期工作。
立即学习“Java免费学习笔记(深入)”;
你是 TypeScript 项目架构专家,专注于脚手架搭建生产就绪的 Node.js 和前端应用。生成包含现代工具链(pnpm、Vite、Next.js)、类型
如何处理不同错误类型的差异化重试策略
在实际场景中,并非所有错误都适合重试,例如网络超时可能需要重试,而参数错误则不应重试。可以通过在捕获错误时检查错误类型或状态码来决定是否继续循环。修改包装函数,使其接受一个可选的错误过滤函数,仅当错误符合特定条件时才触发重试逻辑,否则直接终止并返回错误。

function smartRetry(fn, maxRetries = 3, delay = 1000, shouldRetry = null) {
return new Promise((resolve, reject) => {
let attempts = 0;
function execute() {
fn().then(resolve).catch(error => {
attempts++;
// 默认策略:所有错误都重试
const isRetryable = shouldRetry ? shouldRetry(error) : true;
if (isRetryable && attempts <= maxRetries) {
console.log(`Retry ${attempts}/${maxRetries} for error:`, error.message);
setTimeout(execute, delay);
} else {
reject(error);
}
});
}
execute();
});
}
// 模拟带有状态码的请求
const apiCall = () => new Promise((res, rej) => {
const status = Math.random() > 0.7 ? 500 : 400;
if (status === 500) rej(new Error('Server Error'));
else rej(new Error('Client Error'));
});
// 仅重试服务器错误
smartRetry(apiCall, 3, 1000, (err) => err.message.includes('Server'))
.then(data => console.log('Result:', data))
.catch(err => console.error('Stopped:', err.message));这段代码引入了 shouldRetry 回调函数,允许调用者根据错误对象的内容动态决定重试行为。在 catch 块中,首先评估 isRetryable 标志,只有当该标志为真且未达到最大重试次数时,才执行延迟后的递归调用。示例中使用了 apiCall 模拟返回不同 HTTP 状态码的场景,并通过 shouldRetry 筛选出仅包含 'Server' 字样的错误进行重试,从而实现对客户端错误的快速失败处理。
重试过程中如何获取最终的成功或失败原因
当重试机制启动后,外部调用者需要通过标准的 Promise 链式调用来获取最终结果。如果所有重试均成功,then 块将接收到最后一次成功的返回值;如果所有重试均失败,catch 块将接收到最后一次失败时的错误对象。这意味着重试过程对调用者是透明的,它只关心最终的决议状态,而不需要手动管理中间的重试状态。

















