Hendo
Hendo

Reputation: 311

How can I rate limit how fast a javascript function allows itself to 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?

Upvotes: 31

Views: 28156

Answers (12)

Zied Feki
Zied Feki

Reputation: 872

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.`);
}

Upvotes: 0

Dan
Dan

Reputation: 3756

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

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

Upvotes: 1

Stephen
Stephen

Reputation: 3432

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



Upvotes: 7

thisismydesign
thisismydesign

Reputation: 25172

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

Upvotes: 9

Mike Schall
Mike Schall

Reputation: 5899

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)

Upvotes: 1

Narayan Prusty
Narayan Prusty

Reputation: 1

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/

Upvotes: -1

benathon
benathon

Reputation: 7653

You can also use the SugarJS function "throttle":

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

Upvotes: 0

Matthew O&#39;Riordan
Matthew O&#39;Riordan

Reputation: 8211

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

Upvotes: 5

Warty
Warty

Reputation: 7405

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

Upvotes: -3

user216441
user216441

Reputation:

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

Upvotes: 4

Jose
Jose

Reputation: 23

try setinterval( "function()", 500)

Upvotes: -3

&#211;lafur Waage
&#211;lafur Waage

Reputation: 70011

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.

Upvotes: 2

Related Questions