一个函数解决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 };```