public
Last active

Rate limiting function calls with JavaScript and Underscore.js

  • Download Gist
rate_limit.js
JavaScript
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
/* Extend the Underscore object with the following methods */
 
// Rate limit ensures a function is never called more than every [rate]ms
// Unlike underscore's _.throttle function, function calls are queued so that
// requests are never lost and simply deferred until some other time
//
// Parameters
// * func - function to rate limit
// * rate - minimum time to wait between function calls
// * async - if async is true, we won't wait (rate) for the function to complete before queueing the next request
//
// Example
// function showStatus(i) {
// console.log(i);
// }
// var showStatusRateLimited = _.rateLimit(showStatus, 200);
// for (var i = 0; i < 10; i++) {
// showStatusRateLimited(i);
// }
//
// Dependencies
// * underscore.js
//
_.rateLimit = function(func, rate, async) {
var queue = [];
var timeOutRef = false;
var currentlyEmptyingQueue = false;
var emptyQueue = function() {
if (queue.length) {
currentlyEmptyingQueue = true;
_.delay(function() {
if (async) {
_.defer(function() { queue.shift().call(); });
} else {
queue.shift().call();
}
emptyQueue();
}, rate);
} else {
currentlyEmptyingQueue = false;
}
};
return function() {
var args = _.map(arguments, function(e) { return e; }); // get arguments into an array
queue.push( _.bind.apply(this, [func, this].concat(args)) ); // call apply so that we can pass in arguments as parameters as opposed to an array
if (!currentlyEmptyingQueue) { emptyQueue(); }
};
};

@arronmabrey, no problem, glad someone's using it!

Really cool, thanks!

Hi @mattheworiordan, great work. Can I get some license info on this?

Please sign in to comment on this gist.

Something went wrong with that request. Please try again.