一个函数解决90%的异步请求稳定性问题
* 异步重试函数
* @param {Function} asyncFn - 要执行的异步函数
* @param {number} maxRetries - 最大重试次数(包括首次调用)
* @param {number} retryInterval - 重试间隔(毫秒)
* @returns {Promise<any>} - 返回异步函数的结果或抛出错误
*/
async function retryAsync(asyncFn, maxRetries = 3, retryInterval = 1000) {
// 验证参数
if (typeof asyncFn !== 'function') {
throw new TypeError('第一个参数必须是函数');
}
if (!Number.isInteger(maxRetries) || maxRetries < 1) {
throw new TypeError('最大重试次数必须是正整数');
}
if (!Number.isInteger(retryInterval) || retryInterval < 0) {
throw new TypeError('重试间隔必须是非负整数');
}
let lastError;
for (let attempt = 1; attempt <= maxRetries; attempt++) {
try {
// 尝试执行异步函数
const result = await asyncFn();
console.log(`第 ${attempt} 次尝试成功`);
return result;
} catch (error) {
lastError = error;
console.warn(`第 ${attempt} 次尝试失败: ${error.message}`);
// 如果是最后一次尝试,不再等待
if (attempt === maxRetries) {
console.error(`已达到最大重试次数 (${maxRetries}),操作失败`);
break;
}
// 等待指定间隔后重试
console.log(`等待 ${retryInterval}ms 后重试...`);
await sleep(retryInterval);
}
}
// 所有尝试都失败,抛出最后的错误
throw lastError;
}
/**
* 睡眠函数,用于等待指定时间
* @param {number} ms - 等待的毫秒数
* @returns {Promise<void>}
*/
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
// 使用示例
async function exampleUsage() {
// 模拟一个可能失败的异步函数
let callCount = 0;
const unreliableAsyncFunction = async () => {
callCount++;
console.log(`调用异步函数,第 ${callCount} 次`);
// 模拟失败:前两次失败,第三次成功
if (callCount < 3) {
throw new Error(`模拟失败,第 ${callCount} 次调用`);
}
return { success: true, data: '这是返回的数据', callCount };
};
try {
// 尝试最多5次,每次间隔2秒
const result = await retryAsync(unreliableAsyncFunction, 5, 2000);
console.log('最终成功:', result);
return result;
} catch (error) {
console.error('最终失败:', error.message);
throw error;
}
}
// 测试
exampleUsage().catch(() => {
console.log('主流程捕获到错误');
});
// 更简洁的版本(去掉日志和参数验证)
async function retryAsyncSimple(asyncFn, maxRetries = 3, retryInterval = 1000) {
let lastError;
for (let attempt = 1; attempt <= maxRetries; attempt++) {
try {
return await asyncFn();
} catch (error) {
lastError = error;
if (attempt === maxRetries) break;
if (retryInterval > 0) {
await new Promise(resolve => setTimeout(resolve, retryInterval));
}
}
}
throw lastError;
}
// 支持指数退避策略的版本
async function retryAsyncWithBackoff(
asyncFn,
maxRetries = 3,
baseInterval = 1000,
maxInterval = 10000
) {
let lastError;
for (let attempt = 1; attempt <= maxRetries; attempt++) {
try {
return await asyncFn();
} catch (error) {
lastError = error;
if (attempt === maxRetries) break;
// 指数退避:等待时间逐渐增加
const delay = Math.min(
baseInterval * Math.pow(2, attempt - 1),
maxInterval
);
await new Promise(resolve => setTimeout(resolve, delay));
}
}
throw lastError;
}
// 导出函数(如果是模块环境)
// export { retryAsync, retryAsyncSimple, retryAsyncWithBackoff };```
浙公网安备 33010602011771号