JS for循环发fetch请求报请求过多 如何实现每秒10次限流
请求限流实现方案
你遇到的「请求发送过多」报错,是因为原代码的for循环会在事件循环中瞬间把所有fetch请求全部发出,完全没有发送间隔,极易触发接口的频率限制。要实现每秒10次的限流,只需要控制请求发起间隔为100ms即可(1000ms ÷ 10次 = 单次请求间隔100ms)。
可直接替换的实现代码
const accesstoken = token2.access_token; // 延时工具函数 const sleep = (ms) => new Promise(resolve => setTimeout(resolve, ms)); // 限流发送请求 async function sendLimitedRequests() { const result = []; for (let i = 0; i < slug.length; i++) { const requestPromise = fetch(`https://us.api.blizzard.com/profile/wow/character/${slug[i]}/${lowercasenames[i]}?namespace=profile-us&locale=en_US`, { method: 'GET', headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${accesstoken}` } }) .then(logresponse => { console.log(logresponse.status); return logresponse }) .then(response => response.json()) .catch(error => { console.log(error); return null; // 捕获单个请求错误,避免批次请求整体中断 }); result.push(requestPromise); // 非最后一个请求时,等待100ms再发起下一个 if (i !== slug.length - 1) { await sleep(100); } } // 所有请求完成后执行后续逻辑 const data = await Promise.all(result); profiledata(data); } // 启动请求 sendLimitedRequests();
实现说明
- 核心是用
async/await配合延时函数,每发起一个请求就等待100ms再发下一个,1秒内刚好发出10个请求,完全匹配限流要求 - 优化了原代码硬编码循环长度为5的问题,直接以
slug数组长度作为循环终止条件,避免后续数组长度变化导致的请求遗漏、下标越界问题 - 给请求catch分支补充了null返回逻辑,单个请求报错不会导致
Promise.all直接失败中断,保证剩余正常请求的结果可以正常传入后续处理函数 - 如果后续批量请求量级提升,可以替换为令牌桶、滑动窗口的专业限流逻辑,当前实现对于千级以内的批量请求场景完全够用
注意:如果接口除了QPS限制还有并发数限制(比如同时只允许3个在途请求),可以在当前间隔控制的基础上补充并发数控制逻辑,你当前每秒10次的需求仅靠间隔控制就可以满足。
内容的提问来源于stack exchange,提问作者Zeronir
相关产品推荐
相关产品推荐

