Mia Mia - 1 year ago 89
Javascript Question

Simple throttle in js

I am looking for a simple throttle in JS. I know libraries like lodash and underscore has it, butonly for one function it will be overkill to include any of those libraries.

I was also checking if jquery has a similar function - could not find.

I have found one working throttle, and here is the code:

function throttle(fn, threshhold, scope) {
threshhold || (threshhold = 250);
var last,
return function () {
var context = scope || this;

var now = +new Date,
args = arguments;
if (last && now < last + threshhold) {
// hold on to it
deferTimer = setTimeout(function () {
last = now;
fn.apply(context, args);
}, threshhold);
} else {
last = now;
fn.apply(context, args);

The problem with this is: it fires the functiononce more after the throttle time iscomplete. So lets assume I made athrottle that fires every 10 seconds on keypress - if I do keypress 2 times, it will still fire the second keypress when 10 seconds are completed. I do not want this behavior.

Any help is appreciated.

Answer Source

I would use the underscore.js source code to find a well tested version of this function.

Here is the slightly modified version to remove all references to underscore.js himself:

// Returns a function, that, when invoked, will only be triggered at most once
// during a given window of time. Normally, the throttled function will run
// as much as it can, without ever going more than once per `wait` duration;
// but if you'd like to disable the execution on the leading edge, pass
// `{leading: false}`. To disable execution on the trailing edge, ditto.
function throttle(func, wait, options) {
  var context, args, result;
  var timeout = null;
  var previous = 0;
  if (!options) options = {};
  var later = function() {
    previous = options.leading === false ? 0 : Date.now();
    timeout = null;
    result = func.apply(context, args);
    if (!timeout) context = args = null;
  return function() {
    var now = Date.now();
    if (!previous && options.leading === false) previous = now;
    var remaining = wait - (now - previous);
    context = this;
    args = arguments;
    if (remaining <= 0 || remaining > wait) {
      if (timeout) {
        timeout = null;
      previous = now;
      result = func.apply(context, args);
      if (!timeout) context = args = null;
    } else if (!timeout && options.trailing !== false) {
      timeout = setTimeout(later, remaining);
    return result;

Edit 1: Removed another reference to underscore, thx to Zettam's comment

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download