如何对axios.all与axios.spread批量请求做限流处理?
问题描述
找不到任何关于使用axios.all发起并发批量请求时做限流处理的文档或示例,了解到axiom-rate-limit但没找到结合axios.all/axios.spread的实现方案。
原始批量请求函数
async function bulkAxios(url, idArray) { var token = "BEARER-TOKEN" const AuthStr = "Bearer ".concat(token); for (var i in idArray) { var config = { method: "get", url: url + idArray[i], headers: { Authorization: AuthStr }, }; let newPromise = axios(config) axiosArray.push(newPromise) } console.log("Initiating bulk promises for bulkAxios api calls.") const p = Promise .all(axiosArray) .then(axios.spread((...responses) => { responses = responses.map(item => item.data) console.log('All Axios API calls succeeded.'); return(responses) })) .catch(function (error) { console.log(error); }); return(p); }
尝试添加限流的过程
首先创建限流包装后的axios实例:
const apiRequest = rateLimit(axios.create(), { maxRequests: 2, perMilliseconds: 1000, maxRPS: 2 })
修改后的函数(存在错误):
async function bulkAxios(url, idArray) { var token = "BEARER-TOKEN" const AuthStr = "Bearer ".concat(token); for (var i in idArray) { var config = { method: "get", url: url + idArray[i], headers: { Authorization: AuthStr }, }; let newPromise = http(config) axiosArray.push(newPromise) } console.log("Initiating bulk promises for bulkAxios api calls.") const p = Promise .all(axiosArray) .then(http.spread((...responses) => { responses = responses.map(item => item.data) console.log('All Axios API calls succeeded.'); return(responses) })) .catch(function (error) { console.log(error); }); return(p); }
出现的错误
.then(apiRequest.spread((...responses) => { ^ TypeError: apiRequest.spread is not a function at bulkAxios (/Users/user/Desktop/app/api/index.js:160:26) at process.processTicksAndRejections (node:internal/process/task_queues:95:5) at async routeHandler (/Users/user/Desktop/app/api/index.js:209:25)
改回axios.spread后代码可运行,但无法确认限流是否生效。
8/24更新后的代码
// limits axios api requests to 50 per second const apiRequest = rateLimit(axios.create(), { maxRequests: 50, perMilliseconds: 1000 }); async function bulkAxios(url, idArray) { var token = "BEARER-TOKEN" const AuthStr = "Bearer ".concat(token); for (var i in idArray) { var config = { method: "get", url: url + idArray[i], headers: { Authorization: AuthStr }, }; let newPromise = apiRequest(config); axiosArray.push(newPromise) } console.log("Initiating bulk promises for bulkAxios api calls.") const p = Promise .all(axiosArray) .then(axios.spread((...responses) => { responses = responses.map(item => item.data) console.log('All Axios API calls succeeded.'); return(responses) })) .catch(function (error) { console.log(error); }); return(p); }
解决方案
1. 关于apiRequest.spread报错的原因
axiom-rate-limit仅对axios的请求发送逻辑做了限流包装,不会继承axios的静态方法spread,所以spread必须直接使用axios.spread,你改回的做法是正确的。
2. 验证限流是否生效
给apiRequest添加请求拦截器,打印每个请求的发起时间,就能直观确认限流是否工作:
apiRequest.interceptors.request.use(config => { console.log(`请求发起时间: ${new Date().toISOString()}`); return config; });
运行后查看控制台时间戳,如果请求按你设置的频率(如50次/秒)依次发起,说明限流已生效。
3. 当前代码的逻辑说明
你现在的写法是先创建所有限流包装后的请求Promise,再用Promise.all等待结果。axiom-rate-limit的限流逻辑是在调用apiRequest(config)时触发的,所以即使所有Promise都被提前创建,它们也会按照限流规则依次发起请求,不会一次性全部并发,这部分逻辑是正常的。
4. 代码优化建议
- 不要用
for...in遍历数组,改用for...of或forEach,避免遍历到数组原型上的额外属性。 - 将
axiosArray声明在函数内部,避免全局变量累积之前的请求Promise:
async function bulkAxios(url, idArray) { const axiosArray = []; // 内部声明,避免全局污染 var token = "BEARER-TOKEN" const AuthStr = "Bearer ".concat(token); for (const id of idArray) { // 用for...of遍历数组 var config = { method: "get", url: url + id, headers: { Authorization: AuthStr }, }; let newPromise = apiRequest(config); axiosArray.push(newPromise) } // 后续逻辑不变 }
内容的提问来源于stack exchange,提问作者kiddslopp
相关产品推荐
相关产品推荐

