Skip to content

Instantly share code, notes, and snippets.

@darkterminal
Forked from ionurboz/debounce-throttle.md
Created October 2, 2022 12:56
Show Gist options
  • Save darkterminal/3a248f4ff4b4d3cc6f86b102ccd528ec to your computer and use it in GitHub Desktop.
Save darkterminal/3a248f4ff4b4d3cc6f86b102ccd528ec to your computer and use it in GitHub Desktop.
Simple JavaScript debounce and throttle (Pure, Vanilla, Plain JS)

If you've written any kind of validation on user input, like onkeypress then you'll know that sometimes you want to throttle the amount of times your function runs. A good example of this is Ajax based username validation - you don't want to hit the server on every key press, because most users will be able to write their name in around 1/10th of a second, so you should throttle the ajax request until the input is dormant for 100ms.

So with a bit of magic JavaScript making use of the ever useful closure JavaScript offers, we can create a simple method to handle this for us:

function debounce(fn, delay) {
  var timer = null;
  return function () {
    var context = this, args = arguments;
    clearTimeout(timer);
    timer = setTimeout(function () {
      fn.apply(context, args);
    }, delay);
  };
}

So if you were doing something with jQuery, like a key press validation, you would do this instead:

$('input.username').keypress(debounce(function (event) {
  // do the Ajax request
}, 250));

The keyword this is the input as you would expect, and all the correct arguments are passed to the event handle, i.e. it works the exact same way as you'd expect, except it only fires once the keypress event is idle for 250ms (in this particular case).

Below is an actual throttle function, that fires a message every 250ms by default (rather than at the end of a burst of events):

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

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

So when you use this, moving the mouse around the example below, will echo out the tick on the first time you move, but then every 1 second until you stop moving the mouse:

$('body').on('mousemove', throttle(function (event) {
  console.log('tick');
}, 1000));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment