开发者

How can I rate limit how fast a javascript function allows itself to be called?

开发者 https://www.devze.com 2023-01-01 21:26 出处:网络
I have a JavaScript function which actually ends up making a server-side call.I want to limit the rate at which this function can be called.

I have a JavaScript function which actually ends up making a server-side call. I want to limit the rate at which this function can be called.

What is an easy way I can limit how fast my javascript function will get called by say 200-500 milliseconds or so? Should 开发者_运维百科I use a javascript timer control?


Libraries like bottleneck and node-rate-limiter pretty much cover all use cases.


If your problem involves too much work being created, use a queue:

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);

If you problem involves a function being called too often:

let last = +new Date();

function run() {
  const now = +new Date();
  if (now - last > 5000) { // 5 seconds
    last = now;
    run_once();
  }
}




First you need to establish if you want to rate limit in that you disregard all function calls that are made during the period when you are waiting, or whether you want to simply queue up requests so that you ensure you never make more than X requests per second.

If you want the former solution (disregard new functional calls), then you should look at http://documentcloud.github.com/underscore/#throttle

If you want to rate limit so that you never call your function more than X times per second, but don't lose those function calls altogether, then you need a wholly different solution.

I have written an underscore extension at https://gist.github.com/1084831 You can see a working example at http://jsbin.com/upadif/8/edit#preview


This will not allow the function to run if less than 500 milliseconds have passed since the last call.

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


You can create a flag that is raised when the function is called and start a timer and if this flag is raised then you can not call the function, then after a certain time, the timer is called and he turns off the flag, allowing you to call the function again.

The flag can be anything, like a bool or something.


It kind of depends what functionality you want. Here is a link to a page that has 2 great functions: https://remysharp.com/2010/07/21/throttling-function-calls

throttle: process first call, then throttle next calls based on a threshhold (first and last call will be processed, but only a couple calls in between)

debounce: don't process any calls until function hasn't been called for a delay (only 1 will be called after a call and quite period)


It depends on what you want to do with subsequent calls, where you wanna run it etc.

  • Wait on subsequent calls: throttle-wait
  • Discard subsequent calls lodash.throttle sugar.throttle...
  • More advance like throttle on multiple server or more configs bottleneck

Also serverside throttler like ratelimiter (async-ratelimiter), node-rate-limiter


You can also use the SugarJS function "throttle":

http://sugarjs.com/api/Function/throttle


I would suggest Pat Migliaccio solution found here

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();
    };
}

You can easily test it by creating a loop:

const logMessageLimited = limiter(msg => { console.log(msg); }, 1000);

for (let i = 0; i < 10; i++){
    logMessageLimited(`[Message Log] Action (${i}) rate limited.`);
}


You can use debounce function

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

More information on how debounce function works here http://qnimate.com/javascript-limit-function-call-rate/


try setinterval( "function()", 500)


fooCanBeCalled = true;
function foo(){
   if(!fooCanBeCalled) return;
   //Whatever you want to do
   fooCanBeCalled = false;
   setTimeout(function(){
      {
         fooCanBecalled = true;
      }
   , delayInMilliseconds);
}
0

精彩评论

暂无评论...
验证码 换一张
取 消