使用Axios+array.map()时无法结合async/await与setTimeout的问题
问题分析与解决方案
为什么你的代码会触发429错误?
第一个代码的问题
Promise.all会一次性启动所有map里的异步任务,每个任务内部的await setTimeout是并行等待的——所有任务同时开始计时,334ms后会同时发起API请求,瞬间超过了API每秒3次的限制,自然触发429。
第二个rateLimit代码的问题
你在每次循环里都新建了一个rateLimit实例,每个实例的限流计数器是独立的,相当于每个请求都用了一个全新的限流规则,根本起不到控制速率的作用。
可行的解决方案
方案1:串行请求(简单直接,适合数据量不大的场景)
用普通for循环逐个发起请求,每个请求完成后等待固定时间,确保每秒不超过3次:
import axios from 'axios'; const apiCall = []; for (const item of data || []) { const numeroPedidoBling = item?.numeroPedidoBling; // 发起API请求 const orderData = await axios.get(`${BLING_URL}/${numeroPedidoBling}/json?apikey=${APIKEY}`, { headers: { 'Accept': "application/json" } }); apiCall.push(orderData?.data?.retorno); // 等待334ms再发起下一个请求,控制速率 await new Promise(resolve => setTimeout(resolve, 334)); }
方案2:批量并行+间隔(效率更高,适合大数据量)
每次同时发起3个请求(刚好达到API速率上限),完成后等待1秒再发起下一批,平衡效率和速率控制:
import axios from 'axios'; const batchSize = 3; const apiCall = []; const dataList = data || []; for (let i = 0; i < dataList.length; i += batchSize) { // 截取当前批次的3个数据 const batch = dataList.slice(i, i + batchSize); // 并行处理当前批次的请求 const batchResults = await Promise.all(batch.map(async item => { const numeroPedidoBling = item?.numeroPedidoBling; const orderData = await axios.get(`${BLING_URL}/${numeroPedidoBling}/json?apikey=${APIKEY}`, { headers: { 'Accept': "application/json" } }); return orderData?.data?.retorno; })); apiCall.push(...batchResults); // 如果不是最后一批,等待1秒再继续 if (i + batchSize < dataList.length) { await new Promise(resolve => setTimeout(resolve, 1000)); } }
方案3:修复rateLimit的用法(复用限流实例)
确保只创建一次带限流的axios实例,所有请求复用这个实例,让限流规则生效:
import axios from 'axios'; import rateLimit from 'axios-rate-limit'; // 只初始化一次限流实例,设置每秒最多3次请求 const request = rateLimit(axios.create(), { maxRPS: 3 }); const result = []; for (const item of data || []) { const numeroPedidoBling = item?.numeroPedidoBling; const orderData = await request.get(`${BLING_URL}/${numeroPedidoBling}/json?apikey=${APIKEY}`, { headers: { 'Accept': "application/json" } }); result.push(orderData?.data?.retorno); }
内容的提问来源于stack exchange,提问作者Thiago Robles
相关产品推荐
相关产品推荐

