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

如何用Promise(await)处理多次连续失败的异步请求

实现带自动重试的异步请求函数

嘿,我明白你想要的是一个简洁清晰、能自动重试失败请求的async函数——这其实是异步编程里很常见的需求,咱们可以把重试逻辑和业务请求拆分开来写,既清晰又好维护!

先写一个通用的重试工具函数

首先咱们搞一个通用的retry函数,它负责处理重试的循环逻辑,把具体的异步任务(比如你的HTTP请求)当成参数传进去就行:

async function retry(asyncTask, maxAttempts) {
  let attemptCount = 0;
  while (attemptCount < maxAttempts) {
    try {
      // 执行异步任务,成功就直接返回结果
      return await asyncTask();
    } catch (error) {
      attemptCount++;
      // 如果是最后一次尝试失败,直接抛出错误给上层处理
      if (attemptCount === maxAttempts) {
        throw new Error(`试过${maxAttempts}次都失败了:${error.message}`);
      }
      // 可选:加个指数退避延迟,避免频繁请求压垮服务器
      await new Promise(resolve => setTimeout(resolve, 1000 * attemptCount));
      console.log(`第${attemptCount}次失败,马上进行第${attemptCount + 1}次重试...`);
    }
  }
}

结合你的HTTP请求使用

接下来把你的HTTP请求逻辑封装成一个单独的async函数,然后丢给retry函数就行,这样业务逻辑和重试逻辑完全分离,看着清爽:

// 模拟你的HTTP请求,这里用fetch举例子,你换成自己的请求库也一样
async function makeHttpRequest() {
  // 这里放你HTTP请求前的操作
  console.log("准备发起请求啦...");
  
  const response = await fetch("https://your-api-url.com/your-endpoint");
  if (!response.ok) {
    // 请求返回错误状态码时主动抛出错误,触发重试
    throw new Error(`请求失败,状态码:${response.status}`);
  }
  return await response.json();
}

// 你的主函数
async function func() {
  try {
    // 最多重试3次,你可以改成任意数字n
    const result = await retry(makeHttpRequest, 3);
    console.log("请求成功!拿到的数据:", result);
    // 这里写请求成功后的后续逻辑
  } catch (error) {
    console.error("彻底失败了:", error.message);
    // 处理最终失败的情况
  }
}

// 执行主函数
func();

为啥这么写?给你拆解下逻辑

  • 解耦设计:把重试逻辑抽成通用函数,以后任何需要重试的异步任务都能直接用,不用重复写代码。
  • 清晰的流程:用while循环控制重试次数,每一步的逻辑都一目了然,比嵌套Promise链好维护太多。
  • 错误控制:只有当所有重试都用完了才会抛出最终错误,上层函数可以统一处理失败情况。
  • 友好的重试策略:加了指数退避延迟(每次重试等的时间翻倍),这是后端请求的最佳实践,能减少对服务器的冲击,你也可以根据需求调整延迟时间。

可选扩展:只重试特定错误

如果你的需求是只针对某些错误(比如超时、网络错误)重试,而不是所有错误都重试,可以给retry函数加个参数:

async function retry(asyncTask, maxAttempts, retryableErrorTypes = []) {
  let attemptCount = 0;
  while (attemptCount < maxAttempts) {
    try {
      return await asyncTask();
    } catch (error) {
      attemptCount++;
      // 判断当前错误是否属于需要重试的类型
      const shouldRetry = retryableErrorTypes.length === 0 
        ? true 
        : retryableErrorTypes.some(errType => error instanceof errType);
      
      // 如果是最后一次尝试,或者错误不可重试,就抛出最终错误
      if (attemptCount === maxAttempts || !shouldRetry) {
        throw new Error(`试过${attemptCount}次都失败了:${error.message}`);
      }
      
      await new Promise(resolve => setTimeout(resolve, 1000 * attemptCount));
      console.log(`第${attemptCount}次失败(属于可重试错误),马上重试...`);
    }
  }
}

// 用法示例:只针对超时错误重试
// 假设你有一个自定义的TimeoutError类
retry(makeHttpRequest, 3, [TimeoutError]);

这样写出来的代码既简洁又灵活,完全符合你的需求!

内容的提问来源于stack exchange,提问作者Michele Tuloski Furci

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 04:35:59