You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在原生JavaScript中实现支持取消与错误码判断的Promise重试函数?

带重试、取消机制和HTTP错误码区分的API请求工具函数

针对你需要的具备健壮性的API请求重试函数,以下是优化后的实现,同时解决取消机制和HTTP错误码区分处理两个核心问题:

function retry(fn, retries = 3, delay = 1000) {
  // 用于取消重试的控制器
  const controller = new AbortController();
  const signal = controller.signal;

  const promise = new Promise((resolve, reject) => {
    let timeoutId;

    const attempt = (n) => {
      // 如果已取消,直接终止
      if (signal.aborted) {
        reject(new Error("请求已取消"));
        return;
      }

      fn(signal)
        .then((response) => {
          // 处理HTTP状态码:4xx直接拒绝,不重试
          if (!response.ok) {
            if (response.status >= 400 && response.status < 500) {
              reject(new Error(`HTTP错误:${response.status} ${response.statusText}`));
              return;
            }
            // 5xx错误,进入重试逻辑
            throw new Error(`服务器错误:${response.status} ${response.statusText}`);
          }
          resolve(response);
        })
        .catch((error) => {
          // 如果是取消错误,直接拒绝
          if (error.name === "AbortError") {
            reject(error);
            return;
          }
          // 剩余重试次数为0时,拒绝
          if (n === 0) {
            reject(error);
          } else {
            // 延迟后重试
            timeoutId = setTimeout(() => {
              attempt(n - 1);
            }, delay);
          }
        });
    };

    // 监听取消信号,清理定时器
    signal.addEventListener("abort", () => {
      if (timeoutId) clearTimeout(timeoutId);
    });

    attempt(retries);
  });

  // 给Promise添加cancel方法,外部可调用取消
  promise.cancel = () => {
    controller.abort();
  };

  return promise;
}

// 测试用例
const fetchWithRetry = () => {
  return retry((signal) => 
    fetch("https://jsonplaceholder.typicode.com/todos/95", { signal })
  );
};

// 使用示例
const request = fetchWithRetry();
request
  .then(response => response.json())
  .then(data => console.log(data))
  .catch(error => console.error('请求失败:', error));

// 模拟用户取消(比如页面跳转/关闭时调用)
// setTimeout(() => {
//   request.cancel();
// }, 1500);

核心功能说明

  • 取消机制实现:

    • 借助AbortController和AbortSignal控制请求生命周期,为返回的Promise新增cancel方法,外部可主动触发取消操作
    • 监听abort信号,清理待执行的重试定时器,避免内存泄漏
    • 触发取消后,直接终止后续重试流程并抛出取消错误
  • HTTP错误码区分处理:

    • 请求成功后先校验response.ok,对非2xx状态码分类处理
    • 4xx客户端错误(如401、403)直接拒绝,不进入重试逻辑
    • 5xx服务器错误抛出异常,触发重试流程
    • 网络错误或其他异常同样触发重试,直到耗尽重试次数

使用注意事项

  • 传入的请求函数(如fetch)需要支持接收signal参数,并绑定到请求配置中,才能在取消时终止正在进行的请求
  • 可根据业务需求调整重试次数retries和延迟时间delay
  • 在页面卸载、路由跳转等场景下,调用返回Promise的cancel()方法即可终止所有待重试请求

内容的提问来源于stack exchange,提问作者dram95

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 03:12:41