[英]throttle requests in Node.js
我有一个数组。 我可以使用 foreach 方法遍历它。
data.forEach(function (result, i) {
url = data[i].url;
request(url);
});
请求函数正在向给定的 url 发出 http 请求。 然而,同时发出所有这些请求会导致各种问题。
所以我想我应该通过引入某种计时器来减慢速度。
但我不知道如何将 forach 循环与 setTimeOut/setInterval 结合起来
请注意我是在服务器(nodejs)上而不是在浏览器上执行此操作。
谢谢你的帮助。
由于您的问题是全局性的,因此您应该调整request
函数,以便一次只运行5个请求 - 使用全局静态计数器。 如果你的要求是在类似之前
function request(url, callback) {
ajax(url, callback);
}
现在使用类似的东西
var count = 0;
var waiting = [];
function request(url, callback) {
if (count < 5) {
count++;
ajax(url, function() {
count--;
if (waiting.length)
request.apply(null, waiting.shift());
callback.apply(this, arguments);
});
} else
waiting.push(arguments);
}
data.forEach(function (result, i) {
url = data[i].url;
setTimeout(
function () {
request(url);
},
1000 * (i + 1) // where they will each progressively wait 1 sec more each
);
});
而不是setTimeout
可以让它们按顺序运行。 我假设你的request()
函数有一个callback
参数。
function makeRequest(arr, i) {
if (i < arr.length) {
request(arr[i].url, function() {
i++;
makeRequest(arr, i);
});
}
}
makeRequest(data, 0);
如果您在请求之间需要更多时间,则将setTimeout
添加到回调中。
function makeRequest(arr, i) {
if (i < arr.length) {
request(arr[i].url, function() {
i++;
setTimeout(makeRequest, 1000, arr, i);
});
}
}
makeRequest(data, 0);
你可以使用setTimeout延迟通话。 以下代码将确保每个请求在其之前的请求之后的timerMultiPlier
毫秒之后被调用。
var timerMultiPlier = 1000;
data.forEach(function (result, i) {
setTimeout(function(){
url = data[i].url;
request(url);
}, timerMultiPlier*i );
});
您可以通过索引来抵消每个项目的执行延迟,如下所示:
data.forEach(function (result, i) {
setTimeout(function() {
url = data[i].url;
request(url);
}, i * 100);
});
这将使每次迭代在前一次迭代后执行约100毫秒。 您可以将100
更改为您想要的任何数字以更改延迟。
上述许多解决方案虽然适用于少数几个请求,但在处理成千上万个请求时,会不可避免地扼杀并整理页面。 不是将所有定时器排在一个,而是应该依次对每个定时器进行排序。 如果你的目标是拥有漂亮而又蓬松的代码以及大量的糖和'好吃的东西',那么下面就是你的解决方案。
function miliseconds(x) { return x }
function onceEvery( msTime ){
return {
doForEach: function(arr, eachF){
var i = 0, Len = arr.length;
(function rekurse(){
if (i < Len) {
eachF( arr[i], i, arr );
setTimeout(rekurse, msTime);
++i;
}
})();
}
};
}
漂亮,漂亮,蓬松的糖衣用法:
onceEvery( miliseconds( 150 ) ).doForEach( ["Lorem", "ipsum", "dolar", "un", "sit", "amet"], function(value, index, array){ console.log( value, index ); } ) function miliseconds(x) { return x } function onceEvery( msTime ){ return { doForEach: function(arr, eachF){ var i = 0, Len = arr.length; (function rekurse(){ if (i < Len) { eachF( arr[i], i, arr ); setTimeout(rekurse, msTime); ++i; } })(); } }; }
这个问题的一些补充,只是为了知识库。
创建和异步版本没有递归。
function onceEvery(msTime) {
return {
doForEach: function (eachFunc, paramArray) {
var i = 0, Len = paramArray.length;
(function rekurse() {
if (i < Len) {
eachFunc(paramArray[i], i, paramArray);
setTimeout(rekurse, msTime);
++i;
}
})();
},
doForEachAsync: async function (eachFunc, paramArray, staticParamenters) {
var i = 0, Len = paramArray.length;
while (i < Len) {
await (async function rekurse() {
await eachFunc(paramArray[i], staticParamenters);
setTimeout(() => { }, msTime);
++i;
})();
}
}
};
}
module.exports = {
onceEvery
};
将此代码放入 a.js 并调用如下:
await throttle.onceEvery(100).doForEachAsync(loadJobFunction, arrayParam, { staticParam1, staticParam2, staticParam3 });
使用 async / await 快速节流的一个非常简单的解决方案是创建一个承诺,例如:
const wait = (delay) => new Promise((resolve, _) => {
setTimeout(() => resolve(true), delay)
})
然后在需要暂停时等待它(在async
函数中):
//... loop process
await wait(100)
注意:您需要使用for
循环才能工作, forEach
不会等待。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.