jQuery throttle / debounce: Sometimes, less is more!

|

jQuery throttle / debounce allows you to rate-limit your functions in multiple useful ways. Passing a delay and callback to $.throttle returns a new function that will execute no more than once every delay milliseconds. Passing a delay and callback to $.debounce returns a new function that will execute only once, coalescing multiple sequential calls into a single execution at either the very beginning or end.

Note for non-jQuery users

jQuery isn’t actually required for this plugin, because nothing internal uses any jQuery methods or properties. jQuery is just used as a namespace under which these methods can exist.

Since jQuery isn’t actually required for this plugin, if jQuery doesn’t exist when this plugin is loaded, the methods described below will be created in the Cowboy namespace. Usage will be exactly the same, but instead of $.method() or jQuery.method(), you’ll need to use Cowboy.method().

Throttle versus debounce

Both throttling and debouncing will rate-limit execution of a function, but which is appropriate for a given situation?

Well, to put it simply: while throttling limits the execution of a function to no more than once every delay milliseconds, debouncing guarantees that the function will only ever be executed a single time (given a specified threshhold).

For example, if your function is toggling a state, it won’t be sufficient to simply throttle that function, because given enough calls over time, the throttled function will still execute more than once. In this case, because each subsequent execution “flips” the state back to its previous value, throttling won’t do the trick, but debouncing will.

In another example, the scroll event fires continuously in certain browsers, which means in those browsers, any bound event handler will execute (probably) far more often than you want it to. If your scroll handler is modifying the DOM or performing some other expensive computation, throttling it will guarantee that it executes far less frequently.

But perhaps you don’t need constant updates, but just want to update things when the user has completed the scroll. In this case, debouncing the scroll event handler will guarantee that it doesn’t fire until the user has finished scrolling.

Of course, if you wanted to take this example even further, you could use a pair of debounced event handlers (one using the at_begin parameter, the other not) to do something like set a class only while scrolling. Or only while the user is moving the mouse, or resizing the window, or doing anything else that fires many events sequentially. See an example!

Throttling

Using jQuery throttle / debounce, you can pass a delay and function to $.throttle to get a new function, that when called repetitively, executes the original function (in the same context and with all arguments passed through) no more than once every delay milliseconds.

Throttling can be especially useful for rate limiting execution of handlers on events like resize and scroll. Just take a look at the following usage example or the working throttling examples to see for yourself!

A Visualization

While $.throttle is designed to throttle callback execution, it behaves slightly differently based on how the no_trailing parameter is used.

Throttled with no_trailing specified as false or unspecified: throttled, no_trailing false

Throttled with no_trailing specified as true: throttled, no_trailing true

Key:

  • represents a throttled-function call.
  • represents an actual callback execution.
  • spaces between multiple represent the delay value.
  • is a delay longer than the specified delay value.

Usage example

function log( event ) {
  console.log( $(window).scrollTop(), event.timeStamp );
};

// Console logging happens on window scroll, WAAAY more often
// than you want it to.
$(window).scroll( log );

// Console logging happens on window scroll, but no more than
// once every 250ms.
$(window).scroll( $.throttle( 250, log ) );

// Note that in jQuery 1.4+ you can unbind by reference using
// either the throttled function, or the original function.
$(window).unbind( 'scroll', log );

Debouncing

Using jQuery throttle / debounce, you can pass a delay and function to $.debounce to get a new function, that when called repetitively, executes the original function just once per “bunch” of calls, effectively coalescing multiple sequential calls into a single execution at either the beginning or end. For more information, see this article explaining debouncing.

Debouncing can be especially useful for rate limiting execution of handlers on events that will trigger AJAX requests. Just take a look at the following usage example or the working debouncing examples to see for yourself!

A Visualization

While $.debounce is designed to debounce callback execution, it behaves slightly differently based on how the at_begin parameter is used.

Debounced with at_begin specified as false or unspecified: debounced, at_begin false

Debounced with at_begin specified as true: debounced, at_begin true

Key:

  • represents a debounced-function call.
  • represents an actual callback execution.
  • is a delay longer than the specified delay value.

Usage example

function ajax_lookup( event ) {
  // Perform an AJAX lookup on $(this).val();
};

// Console logging happens on keyup, for every single key
// pressed, which is WAAAY more often than you want it to.
$('input:text').keyup( ajax_lookup );

// Console logging happens on window keyup, but only after
// the user has stopped typing for 250ms.
$('input:text').keyup( $.debounce( 250, ajax_lookup ) );

// Note that in jQuery 1.4+ you can unbind by reference using
// either the throttled function, or the original function.
$('input:text').unbind( 'keyup', ajax_lookup );

Just take a look at the documentation for methods, arguments and usage, as well as the throttling examples and debouncing examples.

If you have any non-bug-related feedback or suggestions, please let me know below in the comments, and if you have any bug reports, please report them in the issues tracker, thanks!

Post A Comment

  • Any of these HTML tags may be used for style: a, b, i, br, p, strong, em, pre, code.
  • Multi-line JavaScript code should be wrapped in <pre class="brush:js"></pre>
    (supported syntax highlighting brushes: js, css, php, plain, bash, ruby, html, xml)
  • Use &lt; instead of < and &gt; instead of > in the examples themselves.