我有一个JavaScript函数,实际上最终会进行服务端调用。我想限制调用该函数的速率。
有没有简单的方法可以限制我的JavaScript函数的调用速度,比如每200-500毫秒一次?我应该使用JavaScript定时器控件吗?
我有一个JavaScript函数,实际上最终会进行服务端调用。我想限制调用该函数的速率。
有没有简单的方法可以限制我的JavaScript函数的调用速度,比如每200-500毫秒一次?我应该使用JavaScript定时器控件吗?
像bottleneck和node-rate-limiter这样的库基本涵盖了所有使用情况。
const work_queue = [];
function queue(message) {
work_queue.push(message)
}
function run() {
const work = work_queue.shift();
if (work !== undefined) {
scan_one(work);
}
}
setInterval(run, 15);
let last = +new Date();
function run() {
const now = +new Date();
if (now - last > 5000) { // 5 seconds
last = now;
run_once();
}
}
首先,你需要确定你想要的是限制速率,即在等待期间忽略所有的函数调用,还是想要排队请求,以确保你每秒钟不会发出超过X个请求。
如果你想要前一种解决方案(忽略新的功能调用),那么你应该查看http://documentcloud.github.com/underscore/#throttle
如果你想要限制速率,以便你每秒钟不会调用你的函数超过X次,但不要完全失去这些函数调用,那么你需要一个完全不同的解决方案。
我在https://gist.github.com/1084831编写了一个underscore扩展程序。你可以在http://jsbin.com/upadif/8/edit#preview上看到一个工作示例。
如果上一次调用距离现在不到500毫秒,则此函数将无法运行。
(function(window, undefined){
var canCall = true;
window.funcName = function(){
if (!canCall)
return;
//Your function
canCall = false;
setTimeout(function(){
canCall = true;
}, 500);
}
})(window);
当函数被调用时,您可以创建一个标志并启动计时器。如果此标志已被提高,则无法调用该函数。然后,在一定时间后,计时器会触发并关闭标志,允许您再次调用该函数。
该标志可以是任何东西,如布尔值或其他内容。
这有赖于您需要哪些功能。以下是一个页面链接,其中包含两个很棒的功能:
https://remysharp.com/2010/07/21/throttling-function-calls
节流:处理第一个调用,然后根据阈值限制下一个调用(第一个和最后一个调用将被处理,但只有在中间调用几次)
去抖动:在函数未被调用一段时间后不要处理任何调用(在调用和静止期之后仅调用1次)
这取决于您希望如何处理后续调用,以及您想在哪里运行它等因素。
还有像 ratelimiter (async-ratelimiter), node-rate-limiter 这样的服务器端限流器。
function limiter(fn, wait){
let isCalled = false,
calls = [];
let caller = function(){
if (calls.length && !isCalled){
isCalled = true;
calls.shift().call();
setTimeout(function(){
isCalled = false;
caller();
}, wait);
}
};
return function(){
calls.push(fn.bind(this, ...arguments));
caller();
};
}
你可以通过创建一个循环轻松测试它:
const logMessageLimited = limiter(msg => { console.log(msg); }, 1000);
for (let i = 0; i < 10; i++){
logMessageLimited(`[Message Log] Action (${i}) rate limited.`);
}
你可以使用防抖函数
function debounce(func, wait, immediate) {
var timeout;
return function() {
var context = this,
args = arguments;
var later = function() {
timeout = null;
if (!immediate) func.apply(context, args);
};
var callNow = immediate && !timeout;
clearTimeout(timeout);
timeout = setTimeout(later, wait);
if (callNow) func.apply(context, args);
};
};
var logging = debounce(function(){
alert("Heavy task");
}, 5000);
setTimeout(logging, 100);//callback executed after 5 seconds
有关防抖函数如何工作的更多信息,请参见此处http://qnimate.com/javascript-limit-function-call-rate/