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

在for循环中对request-promise进行请求速率限制

用Promise控制API请求速率的解决方案

嘿,我完全懂你这个痛点——在循环里直接发起异步请求时,很容易一下子把所有请求都抛出去,分分钟触发API的速率限制。针对你用request-promise处理175个请求、每10秒最多40次的场景,咱们来聊聊两种靠谱的实现方式:

方案一:串行节流(简单可靠)

这种方式会逐个发送请求,每个请求之间严格间隔250ms,完美匹配每10秒40次的限制(40×250ms=10000ms)。优点是逻辑简单,不容易出错,适合对效率要求不是极致高的场景。

const rp = require('request-promise');

async function throttledRequests(itemIds, delayMs) {
  const results = [];
  // 用for...of配合await实现串行执行
  for (const id of itemIds) {
    try {
      // 发起API请求
      const response = await rp({
        url: `https://api.example.com/items/${id}`,
        json: true // 自动解析JSON响应
      });
      results.push(response);
      // 最后一个请求不需要加延迟
      if (id !== itemIds[itemIds.length - 1]) {
        await new Promise(resolve => setTimeout(resolve, delayMs));
      }
    } catch (err) {
      // 单独处理每个请求的错误,避免一个失败导致全流程中断
      console.error(`请求ID ${id} 失败:`, err.message);
      results.push({ id, error: err.message });
    }
  }
  return results;
}

// 调用示例:替换成你的175个条目ID数组
const itemIds = Array.from({ length: 175 }, (_, i) => i + 1);
throttledRequests(itemIds, 250)
  .then(allResults => {
    console.log('所有请求处理完成:', allResults);
  })
  .catch(globalErr => {
    console.error('全局异常:', globalErr);
  });

方案二:批量并发+批次间隔(效率更高)

如果想更快完成所有请求,可以把请求分成批次——每批次最多40个请求(刚好是10秒内的限额),同一批次内的请求并发发送,批次之间间隔10秒。这样总耗时会比串行短很多(175个请求大概30多秒就能完成)。

const rp = require('request-promise');

async function batchThrottledRequests(itemIds, batchSize, batchDelayMs) {
  const results = [];
  // 把ID数组分割成多个批次
  const batches = [];
  for (let i = 0; i < itemIds.length; i += batchSize) {
    batches.push(itemIds.slice(i, i + batchSize));
  }

  // 逐个处理每个批次
  for (const batch of batches) {
    // 并发处理当前批次的所有请求
    const batchPromises = batch.map(id => 
      rp({ url: `https://api.example.com/items/${id}`, json: true })
        .catch(err => ({ id, error: err.message })) // 捕获单个请求错误
    );
    const batchResults = await Promise.all(batchPromises);
    results.push(...batchResults);

    // 最后一个批次不需要延迟
    if (batch !== batches[batches.length - 1]) {
      await new Promise(resolve => setTimeout(resolve, batchDelayMs));
    }
  }
  return results;
}

// 调用示例:每40个请求为一批,批次间隔10秒
const itemIds = Array.from({ length: 175 }, (_, i) => i + 1);
batchThrottledRequests(itemIds, 40, 10000)
  .then(allResults => {
    console.log('所有请求处理完成:', allResults);
  })
  .catch(globalErr => {
    console.error('全局异常:', globalErr);
  });

几个注意事项

  • 错误处理:一定要给每个请求单独加catch,不然某个请求失败会导致整个Promise.all或者串行流程中断。
  • 速率限制细节:如果API的速率限制是「滚动窗口」(比如任意10秒内不超过40次),那批次间隔可以稍微调整(比如设为10500ms),避免因为批次处理耗时导致窗口重叠触发限制。
  • 模块迁移提示:request-promise已经被官方标记为弃用了,长期来看建议迁移到axios或者node-fetch,不过上面的代码逻辑完全可以适配这些新模块。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.19 09:53:34