如何控制JavaScript HTTP调用频率以避免302(请求过多)错误?
解决HTTP请求频繁导致的限流问题
嘿,我明白你遇到的麻烦了——你加了while循环想减慢请求速度,但服务器还是返回限流响应(虽然302通常是重定向,但大概率是服务器用它来限制请求频率)。问题出在JavaScript的http.get是异步操作,你的同步while阻塞根本没法控制请求的发送节奏:循环会瞬间把所有请求都调度出去,等while结束时,所有请求已经在队列里等着发给服务器了,自然会触发限流。
下面给你两种靠谱的解决方法,能严格控制请求频率:
方法一:用递归串行发送请求(兼容旧版JS)
这种方法会逐个发送请求,只有上一个请求完成(不管成功或失败),延迟指定时间后才会发下一个:
const http = require('http'); function sendRequests(links, delay = 1000) { // 所有请求发完就退出 if (links.length === 0) return; const currentLink = links.shift(); console.log(currentLink); http.get(currentLink, function(res) { console.log("statusCode: ", res.statusCode); // 请求完成后,延迟再发下一个 setTimeout(() => sendRequests(links, delay), delay); }).on('error', function(e) { console.error(e); // 即使出错,也继续发送下一个请求 setTimeout(() => sendRequests(links, delay), delay); }); } // 调用时传入你的链接数组,这里设1秒延迟,可根据服务器规则调整 sendRequests([...linkArray], 1000);
方法二:用async/await(现代JS更清晰)
先把http.get包装成Promise,再用async/await实现串行请求:
const http = require('http'); // 把http.get包装成Promise,方便用await function getRequest(url) { return new Promise((resolve, reject) => { http.get(url, (res) => { resolve(res); }).on('error', (err) => { reject(err); }); }); } async function sendRequests(links, delay = 1000) { for (const link of links) { console.log(link); try { const res = await getRequest(link); console.log("statusCode: ", res.statusCode); } catch (e) { console.error(e); } // 每个请求后延迟指定时间 await new Promise(resolve => setTimeout(resolve, delay)); } } // 调用函数 sendRequests(linkArray, 1000);
额外建议
- 延迟时间别太小:100ms可能还是太频繁,建议从1秒开始测试,根据服务器的限流提示调整
- 处理重定向:如果服务器返回302,你可以在回调里读取
res.headers.location,跟随重定向发送请求 - 添加重试机制:如果某个请求失败,可以重试2-3次再继续下一个,避免因为临时网络问题中断流程
内容的提问来源于stack exchange,提问作者HenryM
相关产品推荐
相关产品推荐

