David Walsh Blog

JavaScript Debounce Function

One of the biggest mistakes I see when looking to optimize existing code is the absence of the debounce function.  If your web app uses JavaScript to accomplish taxing tasks, a debounce function is essential to ensuring a given task doesn’t fire so often that it bricks browser performance.

For those of you who don’t know what a debounce function does, it limits the rate at which a function can fire. A quick example:  you have a resize listener on the window which does some element dimension calculations and (possibly)  repositions a few elements.  That isn’t a heavy task in itself but being repeatedly fired after numerous resizes will really slow your site down.  Why not limit the rate at which the function can fire?

Here’s the basic JavaScript debounce function (as taken from Underscore.js):

// Returns a function, that, as long as it continues to be invoked, will not
// be triggered. The function will be called after it stops being called for
// N milliseconds. If `immediate` is passed, trigger the function on the
// leading edge, instead of the trailing.
function debounce(func, wait, immediate) {
	var timeout;
	return function() {
		var context = this, args = arguments;
		var later = function() {
			timeout = null;
			if (!immediate) func.apply(context, args);
		var callNow = immediate && !timeout;
		timeout = setTimeout(later, wait);
		if (callNow) func.apply(context, args);

You’ll pass the debounce function the function to execute and the fire rate limit in milliseconds.  Here’s an example usage:

var myEfficientFn = debounce(function() {
	// All the taxing stuff you do
}, 250);

window.addEventListener('resize', myEfficientFn);

The function above will only fire once every quarter of a second instead of as quickly as it’s triggered; an incredible performance boost in some cases.

I’m often asked what rate should be used when debouncing, and it’s an impossible question to answer because it depends on the task.  The best way to know is testing different rates yourself and seeing where you notice a slowdown — if you notice it, so will your users!