Throttling function calls

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.

2½ years later, I decide that Ben was right – and nowadays I refer to this as a debounce rather than a throttle. I’ve updated this post so that the function name reflects what it does on the tin, but also add my own throttle function that fires the callback based on a specific frequency. The throttle function will also always fire the first and last message.

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

There’s also a simple rate throttled function in the comments below, that fires on every nth message – though I’d be inclined to tweak it to ensure the first message is delivered

19 Responses to “Throttling function calls”

  1. What an elegant and useful little function! I think the name “throttle” might be a tad misleading, but I’ll be damned if I can come up with a better name! :)

    Ben Alman’s fantastic description of throttling vs. debouncing might be helpful here:

    http://benalman.com/projects/jquery-throttle-debounce-plugin/

    Either way, thanks for sharing!

  2. Heh, I wrote about this yesterday: http://fitzgeraldnick.com/weblog/32/

    So did Angus Croll: http://javascriptweblog.wordpress.com/2010/07/19/a-javascript-function-guard/

    Its a cool technique to say the least.

  3. Good things come in threes ;-)

  4. Why do you use “var args = arguments” instead of “arguments” ?
    Is it only for a better reading experience? For performance (so why?)?
    Thanks

  5. @pop – because the arguments are required inside of the setTimeout firing. If I use arguments in the setTimeout, they’d be blank since I hadn’t passed any in.

  6. The first time I read about this technique (referred to most often as “debouncing”) was in unscriptable’s Debouncing Javascript Methods article.

    Check out my jQuery throttle / debounce plugin (that David linked) for an in-depth explanation of the difference between throttling and debouncing (complete with graphs!), as well as a few “alternate” modes for each.

    Consider that a function can be debounced at either the beginning OR the end of a series of repeated calls. For example, due to the way people type, when “throttling” AJAX requests triggered by keyboard input, you typically want to wait until the user has paused for a moment before submitting the query. On the other hand, when dealing with game input, you may actually want the first—but ONLY the first—keypress, within a given time period, to trigger an action.

    And don’t forget about basic throttling, which is simply rate-limiting a function so that it executes no more than once every N milliseconds. Throttling is especially useful in normalizing the scroll and resize events in IE and Safari, which are fired far more frequently than in Firefox (which can cause problems if you’re doing anything computationally expensive).

  7. @cowboy – I know this technique is called “debouncing” – but in english, fewer developers will know what you mean and throttling, although technically inaccurate, actually is pretty obvious what you’re doing – simplicity of specificity :)

    Equally this article: 3 paragraphs, and 8 lines of code – a lazy developer is a happy developer ;-)

  8. Hello

    thank you for this.
    Never thougt it could be called ‘debouncing’, but I found this – it’s awesome little code snippet!:)

    cute

  9. Good name = “chocke”, or even better jQuery.choke(dn, delay)
    :)

  10. Remy, Just read your book on HTML5- fantastic! I have a question for you completely unrelated to this post. I just thought I might ask you since your knowledge of jQuery is far superior to mine! I simply need to get this jQuery plugin to ‘auto-rotate’ – its called SweetPages – think you could help me out?? Thanks Remy!! Hope you can help.

  11. Balázs Galambosi January 19th, 2011 at 10:21 pm

    Yes it’s pretty awesome for autocomplete (sometimes for mousemove, but the “real” throttle is more likely to be used in that case).

    For the ones who want to use it without jQuery:

    One thing to note is that for IE you need to save (shallow copy) the event object, otherwise the delayed function can’t use it, because it’s only available when the event is active.

  12. Just out of interest, which do you prefer? 100ms or 250ms delay :D

  13. Very elegant. Got it working beautifully on an autocomplete I am making (don’t want to use a whole autocomplete plug in for a few reasons). A problem I ran in to is that I only want it to fire if certain keys are pressed in to the input box (namely, a-zA-Z0-9). For the rest of the keys (arrows, tab, shift, etc), I want to take different actions but I don’t want a delay to occur when those select buttons are pressed. I have a switch setup on the keyCode to do certain things for certain keys, then the default behavior is executing the AJAX fetch a list of suggestions. Any idea how I could use the throttle function in the default behavior of that switch? simply: throttle(function() { /* fetch code */ }); does not work, but also does not produce any errors. I’m kind of a JS/jQuery noob, so any assistance would be appreciated. Thanks.

  14. humm, its really helpful for me cause, before i was doing that silly trick to call server on every keyperss. Thanks a lot to describe and share.

  15. Thanks for this Remy. I followed cowboy’s link to unscriptable’s article on throttling/debouncing. If your example above is really debouncing then I guess an actual throttle function would look like this right?:

    
    var throttle = function(func, rate){
        var counter = 0;
        return function(){
            var context = this;
            var args = arguments;
            counter++;
            if(counter === rate){
                func.apply(context, args);
                counter = 0;
            }
        }
    }
    
  16. you should checkout underscore.js – it has a whole load of utility functions like this.

  17. How does this throttle behave for slow functions? Will they get stacked of does the threshold indicate the idle time?

  18. Hi,

    I am working on a auto search function. Here, i want to execute the function after 2 second of last key press.(exactly same requirement as in http://stackoverflow.com/questions/4364729/jquery-run-code-2-seconds-after-last-keypress ). I m using this code but it is not working fine.

    
        function throttle(f, delay)
        {
            var timer = null;
            return function()
            {
                var context = this, args = arguments;
                clearTimeout(timer);
                timer = window.setTimeout(function()
                {
                    f.apply(context, args);
                },
                delay || 500);
            };
        }
    
        function searchfunc()
        {
    
            alert(document.getElementById('Searchtxt').value);
        }
    

    Will you please help me out.

    Thanks in advance,
    Shruti

  19. Hi, I think there’s a bug in your throttle function, you still need to `clearTimeout(deferTimer);` in you `else` clause, before you `fn.apply(context, args);` Otherwise it is possible for deferred and not deferred function invocations to be run with less that `threshold` interval.

Leave a Reply
Not required

CODE: Please escape code and wrap in <pre><code>, doing so will automatically syntax highlight