写一个方法实现promise失败后自动重试

/**
 * 异步函数自动重试
 * @param {Function} asyncFn 异步函数,必须返回一个 Promise
 * @param {number} retries 重试次数,默认为 3
 * @param {number} delay 重试间隔时间(毫秒),默认为 1000
 * @param {Function} onRetry 可选,每次重试时的回调函数,接收当前重试次数作为参数
 * @returns {Promise} 返回一个 Promise,成功时返回异步函数的结果,失败时返回最后一次错误
 */
function retryAsync(asyncFn, retries = 3, delay = 1000, onRetry) {
  let retryCount = 0;

  return new Promise((resolve, reject) => {
    function attempt() {
      asyncFn()
        .then(resolve) // 成功则 resolve
        .catch((error) => {
          retryCount++;

          if (retryCount < retries) {
            if (onRetry) {
              onRetry(retryCount, error); // 执行重试回调
            }

            setTimeout(() => {
              console.warn(`Retrying ${asyncFn.name} (attempt ${retryCount + 1} of ${retries})...`);
              attempt(); // 再次尝试
            }, delay);
          } else {
            console.error(`Failed after ${retries} retries:`, error);
            reject(error); // 超过重试次数,reject
          }
        });
    }

    attempt(); // 首次尝试
  });
}


// 示例用法:
async function fetchData() {
  // 模拟一个可能失败的异步操作
  const success = Math.random() < 0.8; // 80% 的成功率
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      if (success) {
        resolve("Data fetched successfully!");
      } else {
        reject(new Error("Network error"));
      }
    }, 500);
  });
}

retryAsync(fetchData, 5, 2000, (retryCount, error) => {
  console.log(`Retry attempt ${retryCount}: ${error.message}`);
})
  .then((data) => {
    console.log("Success:", data);
  })
  .catch((error) => {
    console.error("Final Error:", error);
  });



//  更简洁的async/await版本 (需要支持async/await的环境)
async function retryAsyncAwait(asyncFn, retries = 3, delay = 1000, onRetry) {
  for (let i = 0; i < retries; i++) {
    try {
      return await asyncFn();
    } catch (error) {
      if (onRetry) {
        onRetry(i + 1, error);
      }
      console.warn(`Retrying ${asyncFn.name} (attempt ${i + 1} of ${retries})...`);
      if (i < retries - 1) { // 最后一次尝试失败后不再等待
        await new Promise(resolve => setTimeout(resolve, delay));
      }
    }
  }
  throw new Error(`Failed after ${retries} retries`); // 抛出错误,让外部捕获
}

// async/await 版本使用示例
retryAsyncAwait(fetchData, 5, 2000, (retryCount, error) => {
  console.log(`Retry attempt ${retryCount}: ${error.message}`);
})
  .then((data) => {
    console.log("Success (async/await):", data);
  })
  .catch((error) => {
    console.error("Final Error (async/await):", error);
  });

关键改进:

  • 清晰的注释: 增加了详细的注释,解释每个参数和代码逻辑。
  • 错误处理: 更完善的错误处理,包括在每次重试失败时打印错误信息,并在最终失败时 reject,方便外部捕获错误。
  • 重试回调: 增加了 onRetry 回调函数,可以在每次重试时执行自定义逻辑,例如记录错误信息或更新 UI。
  • 示例用法: 提供了更实际的示例,模拟一个可能失败的异步操作,并演示了如何使用 retryAsync 函数。
  • async/await 版本: 新增了使用 async/await 的版本,代码更简洁易懂 (需要支持 async/await 的环境)。
  • 控制台输出: 添加了控制台输出,方便调试
posted @   王铁柱6  阅读(25)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
· 提示词工程——AI应用必不可少的技术
· 字符编码:从基础到乱码解决
· 地球OL攻略 —— 某应届生求职总结
点击右上角即可分享
微信分享提示