如何对 JavaScript 函数调用速率进行限制?

29

我有一个JavaScript函数,实际上最终会进行服务端调用。我想限制调用该函数的速率。

有没有简单的方法可以限制我的JavaScript函数的调用速度,比如每200-500毫秒一次?我应该使用JavaScript定时器控件吗?

12个回答

9

如果函数调用第三方API(例如Telegram BOT API),则这应该是首选方法。 - Adarsh Madrecha

7
如果您的问题涉及到创建过多的工作,请使用队列:
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();
  }
}




5

首先,你需要确定你想要的是限制速率,即在等待期间忽略所有的函数调用,还是想要排队请求,以确保你每秒钟不会发出超过X个请求。

如果你想要前一种解决方案(忽略新的功能调用),那么你应该查看http://documentcloud.github.com/underscore/#throttle

如果你想要限制速率,以便你每秒钟不会调用你的函数超过X次,但不要完全失去这些函数调用,那么你需要一个完全不同的解决方案。

我在https://gist.github.com/1084831编写了一个underscore扩展程序。你可以在http://jsbin.com/upadif/8/edit#preview上看到一个工作示例。


4

如果上一次调用距离现在不到500毫秒,则此函数将无法运行。

(function(window, undefined){
    var canCall = true;
    window.funcName = function(){
        if (!canCall) 
            return;
        //Your function
        canCall = false;
        setTimeout(function(){
            canCall = true;
        }, 500);
    }
})(window);

2

当函数被调用时,您可以创建一个标志并启动计时器。如果此标志已被提高,则无法调用该函数。然后,在一定时间后,计时器会触发并关闭标志,允许您再次调用该函数。

该标志可以是任何东西,如布尔值或其他内容。


1

这有赖于您需要哪些功能。以下是一个页面链接,其中包含两个很棒的功能:

https://remysharp.com/2010/07/21/throttling-function-calls

节流:处理第一个调用,然后根据阈值限制下一个调用(第一个和最后一个调用将被处理,但只有在中间调用几次)

去抖动:在函数未被调用一段时间后不要处理任何调用(在调用和静止期之后仅调用1次)


1

0

0
我建议使用Pat Migliaccio的解决方案在这里找到
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.`);
}

-1

你可以使用防抖函数

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/


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接