It’s been brought to my attention that this is also known as a “Debounce” function, which David Walsh has written about before. Thanks to Brian Watson (watsonbot) and Greg Green for bringing this to my attention!
I wanted to share a little trick that I use a lot when building responsive sites that can be a huge help for your front-end performance, which I call the “resize timer”:
Imagine the following scenario: you have a series of horizontally-aligned boxes on your page, which should be equal height. Of course, this is easy to pull off with Flexbox, but browser support isn’t exactly where we want it just yet. Use it where you can, of course, but you might still need a JavaScript-based fallback for older browsers.
Once you’ve picked or written your column equalizer, you probably want to run it whenever the browser resizes, right? After all, changing column width is likely to cause text to wrap differently, which is the nature of the responsive web. Your first instinct may be something like the following:
1 |
$(window).on('resize', myColumnEqualizerFunction); |
Unfortunately, resize
will be called on the window
object for every little change to the browser size, which means myColumnEqualizerFunction()
would be called just as many times, which could get very expensive performance-wise!
Instead, try something like the following:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
// Trigger an 'afterResize' event 500ms after resizing. var resizeTimer; $(window).on('resize', function () { if ( ! resizeTimer ) { resizeTimer = setTimeout(function () { $(window).trigger('afterResize'); resizeTimer = null; }, 500); } }); $(window).on('afterResize', myColumnEqualizerFunction); |
This approach sets up a handle for a window timeout object and checks it every time window.resize
is called (which is far less expensive than calculating something like column heights). If there isn’t already a timeout set one will be created for 500ms from the time this is first invoked, at which point afterResize
will be triggered on the global window
object. We can then attach our column equalization listener to the afterResize
action, ensuring that at most it’s run every 500ms during resize rather than running constantly.
Obviously the 500ms timing could be adjusted to suit your needs, but 500ms seems to be a good balance of performance cost without feeling too “laggy” to end users.
It’s also worth noting that this example uses jQuery, but could very easily be rewritten in vanilla JavaScript.
Amy Hendrix
Nice clear writeup — I’ve learned from experience to do something similar whenever I watch for something on scroll, for the same reasons.
Steve
Thank you!
neemzy
It’s also called throttling ; it’s a pretty common pattern, but it’s always nice to point out its benefits :)
greg5green
Throttling is a little bit different. Throttling will fire it immediately and then not fire again for so many ms. Debouncing will wait so many ms until the last request comes in and then fire.