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

使用Axios批量发起大量HTTP请求的最佳实践方案

问题根因

你当前代码的两个问题本质上是异步逻辑写法错误导致的:

  • forEach 本身不支持异步等待,传入的async回调会被直接加入异步任务队列,forEach执行完同步逻辑后就会直接返回,既不会等待前一个请求完成再触发下一个,也不会把回调里的异步错误抛到外层,所以请求顺序完全随机,部分错误也捕获不到。
  • searchContent 里catch到错误后直接return错误对象,相当于主动吞掉了异常,外层拿到返回值时无法区分是正常响应内容还是错误对象;另外axios响应对象的data属性是同步字段,不需要额外加await,属于冗余写法。
实现方案

根据你对请求顺序、性能的要求选对应写法即可。

方案1:严格按列表顺序串行请求(100%保证执行顺序)

适合对请求先后顺序有强要求的场景,前一个请求拿到结果(成功/失败)后才会发起下一个请求,所有错误都能被精准捕获:

async function searchContent(url) {
  const response = await axios(url);
  return response.data;
}

async function start() {
  const allResults = [];
  // 用for...of循环才能正确等待每一步异步执行
  for (const site of sites) {
    const targetUrl = `https://${site.URL}`;
    try {
      const content = await searchContent(targetUrl);
      allResults.push({
        url: targetUrl,
        success: true,
        data: content
      });
      console.log(`[成功] ${targetUrl}`, content);
    } catch (err) {
      allResults.push({
        url: targetUrl,
        success: false,
        error: err
      });
      console.log(`[失败] ${targetUrl}`, err);
    }
  }
  // 所有请求全部处理完成后才会执行到这里
  console.log('全部请求处理完毕', allResults);
  return allResults;
}

方案2:并发批量请求(性能更高,结果顺序与列表一致)

如果站点数量多、不需要严格的请求先后顺序,用并发请求速度更快,配合Promise.allSettled可以拿到所有请求的结果,不会因为单个请求失败导致整个流程中断,最终返回的结果数组顺序和原站点列表顺序完全一致:

async function start() {
  // 批量生成请求任务
  const requestTasks = sites.map(site => {
    const targetUrl = `https://${site.URL}`;
    return searchContent(targetUrl)
      .then(data => ({
        url: targetUrl,
        success: true,
        data: data
      }))
      .catch(err => ({
        url: targetUrl,
        success: false,
        error: err
      }));
  });
  // 等待所有请求(无论成功失败)全部完成
  const allResults = await Promise.allSettled(requestTasks);
  // 统一处理结果
  allResults.forEach(taskRes => {
    if (taskRes.status === 'fulfilled') {
      console.log(taskRes.value);
    }
  });
  console.log('全部请求处理完毕', allResults);
  return allResults;
}

如果站点数量过大,一次性发全部请求可能触发浏览器同域并发限制、打挂目标站点,可以加一层并发数控制,比如最多同时发3个请求:

// 通用并发池工具
async function asyncPool(limit, list, iterator) {
  const results = [];
  const runningTasks = [];
  for (const item of list) {
    const task = Promise.resolve().then(() => iterator(item));
    results.push(task);
    if (limit <= list.length) {
      const done = task.then(() => runningTasks.splice(runningTasks.indexOf(done), 1));
      runningTasks.push(done);
      if (runningTasks.length >= limit) {
        await Promise.race(runningTasks);
      }
    }
  }
  return Promise.all(results);
}

// 调用示例,最大并发数设为3
async function start() {
  const allResults = await asyncPool(3, sites, async (site) => {
    const targetUrl = `https://${site.URL}`;
    try {
      const content = await searchContent(targetUrl);
      return { url: targetUrl, success: true, data: content };
    } catch (err) {
      return { url: targetUrl, success: false, error: err };
    }
  });
  console.log('全部请求处理完毕', allResults);
  return allResults;
}
避坑提醒
  • 不要用forEach、map这类数组遍历方法处理需要串行等待的异步逻辑,这类方法内部没有对异步回调的等待机制,只会同步注册所有回调,顺序和错误都不可控。
  • 批量异步任务不要直接用Promise.all,只要其中一个任务reject,整个Promise.all会立即失败,其他还在执行的任务结果会丢失,需要拿全量结果时优先用Promise.allSettled。
  • 异步请求不要在底层通用方法里吞错,要么返回带明确状态标识的结构,要么把错误向上抛出交给业务层处理,避免出现错误被静默吃掉难以排查的问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 14:42:24