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

批量API请求分批处理及批次间超时设置问题求助

解决大规模API请求的超时与403问题

问题核心

一次性用Promise.all发起1000次API请求时,触发了API的限流机制,导致超时和随机403错误。你尝试的两种方案都没生效,核心原因是提前执行了所有请求,并发控制逻辑根本没起到作用。

失效方案分析

1. Bluebird方案失效原因

你先通过requests.map把所有请求转换成Promise并立即执行了,之后再用BlueBirdPromise.map去处理这些已经在运行的Promise——这时候请求早就发出去了,concurrency配置完全没意义,只是在等待结果而已。

2. 原生批量方案失效原因

同样的问题:requests.map(async request => await service.retryFailedRequest(request))会立即触发所有1000次请求,生成的是1000个已处于pending状态的Promise,不是待执行的函数。后续的分批和延迟逻辑对已经发起的请求没有任何影响。

正确解决方案

方案1:修正Bluebird并发控制

直接把请求数组传给BlueBirdPromise.map,并传入请求执行逻辑,让Bluebird控制请求的执行时机:

const retry = async (requests: API.CarFailedRequest[]) => {
  setIsLoading(true);
  const results = await BlueBirdPromise.map(
    requests,
    async (request) => {
      try {
        await service.retryFailedRequest(request);
        return { status: true, request };
      } catch (e) {
        return { status: false, request };
      }
    },
    { concurrency: 10 } // 控制同时发起10个请求
  );
  setIsLoading(false);
  // 可根据results统计成功/失败请求
};

方案2:原生实现并发控制

无需第三方库,核心是将请求逻辑包装成函数,延迟执行,再通过代码控制并发数或分批执行。

方式A:分批执行(每批N个,批次间加延迟)

适合API对请求频率限制严格的场景:

// 批量处理函数:接收请求执行函数数组、批次延迟、每批数量
const processRequestsWithDelay = async (
  requestFns: (() => Promise<any>)[],
  delaySeconds: number,
  batchSize: number
) => {
  const results = [];
  for (let i = 0; i < requestFns.length; i += batchSize) {
    const batch = requestFns.slice(i, i + batchSize);
    // 执行当前批次所有请求
    const batchResults = await Promise.all(batch.map(fn => fn()));
    results.push(...batchResults);
    // 非最后一批则添加延迟
    if (i + batchSize < requestFns.length) {
      await new Promise(resolve => setTimeout(resolve, delaySeconds * 1000));
    }
  }
  return results;
};

const retry = async (requests: API.CarFailedRequest[]) => {
  setIsLoading(true);
  // 包装请求为函数,不立即执行
  const requestFns = requests.map(request => () => 
    service.retryFailedRequest(request)
  );
  // 每批5个请求,批次间隔5秒
  const results = await processRequestsWithDelay(requestFns, 5, 5);
  // 处理结果,标记成功/失败
  const processedResults = results.map((_, idx) => ({
    status: !!_,
    request: requests[idx]
  }));
  setIsLoading(false);
};

方式B:严格控制并发数(始终保持N个请求运行)

适合需要更高执行效率的场景,无需等整批完成再启动下一批:

// 创建限流器:控制同时运行的请求数量
const createRateLimiter = (concurrency: number) => {
  const queue: (() => Promise<any>)[] = [];
  let activeCount = 0;

  const execute = async () => {
    if (activeCount >= concurrency || queue.length === 0) return;
    activeCount++;
    const fn = queue.shift();
    try {
      await fn!();
    } catch (e) {
      console.error('请求失败:', e);
    } finally {
      activeCount--;
      execute();
    }
  };

  return {
    // 添加待执行的请求函数
    add: (fn: () => Promise<any>) => {
      queue.push(fn);
      execute();
    },
    // 等待所有请求完成
    wait: () => new Promise(resolve => {
      const checkCompletion = () => {
        if (activeCount === 0 && queue.length === 0) resolve(null);
        else setTimeout(checkCompletion, 100);
      };
      checkCompletion();
    })
  };
};

const retry = async (requests: API.CarFailedRequest[]) => {
  setIsLoading(true);
  const limiter = createRateLimiter(10); // 同时运行10个请求
  const results: { status: boolean; request: API.CarFailedRequest }[] = [];

  requests.forEach(request => {
    limiter.add(async () => {
      try {
        await service.retryFailedRequest(request);
        results.push({ status: true, request });
      } catch (e) {
        results.push({ status: false, request });
      }
    });
  });

  await limiter.wait(); // 等待所有请求执行完毕
  setIsLoading(false);
};

关键注意事项

  • 所有并发控制方案的核心是不要提前执行请求,必须把请求逻辑包装成函数,在需要的时候才调用执行。
  • 根据API的限流规则调整concurrency(并发数)和延迟时间,如果仍出现403,可进一步降低并发数或增加延迟。
  • 建议在请求失败时添加重试逻辑(比如最多重试3次),提升成功率。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 06:45:00