DEV Community 👩‍💻👨‍💻

Cover image for Borrowing a JavaScript Debounce
Nathan Pasko
Nathan Pasko

Posted on • Updated on

Borrowing a JavaScript Debounce

Sometimes, we end up doing heavy things like running functions whenever a user scrolls a web page. The problem arises not from the block of code we're trying to run, but from running it too many times in too short a timeframe. Again, scrolling is a good example of this kind of situation, because if a user scrolls the page from bottom to top they'll trigger the event listener many times in just a second or two.

Situations like this where we need to optimize our JavaScript might benefit from a debounce function. We can use a debounce function like the once below, adapted from Underscore.js, to limit how often a block of code is run.

More specifically--we pass a function (the block of code we want to run) and a number of milliseconds to our debounce. Our debounce then ensures that instead of calling that function immediately on time, it only calls the function once the call has ceased for our specified number of milliseconds. This is not the same as throttling, though the results can be similar.

Hold onto this debounce implementation:

var debounce = (func, wait, immediate) => {
    return function() {
      var context = this;
      var later = function() {
        var args = arguments;
        if (!immediate) {
          func.apply(context, args);
Enter fullscreen mode Exit fullscreen mode

Using it is simple. Let's continue along with our scrolling example. Imagine we have a function called logScroll() that we want to trigger when the user scrolls our page. We can use debounce() while setting that event listener to ensure our function only triggers once, half a second after scrolling ceases. So we pass two arguments to debounce(): the function we want to debounce, and the length of time in milliseconds to wait.

// Code we want to trigger on scroll
function logScroll() {

// Set up the event listener using debounce
document.addEventListener('scroll', debounce(logScroll, 500));
Enter fullscreen mode Exit fullscreen mode

Using debounce() in our triggering of logScroll() improves performance because we only call logScroll() once per scroll action, instead of calling it constantly during every moment of scrolling.

You may have noticed that this debounce method also takes a third argument, called immediate. Since in our example we didn't pass in a third argument, immediate is undefined, however we can pass a true value into immediate and force logScroll() to trigger when scrolling begins rather than ends. The 500 millisecond wait before logScroll() can be called again still occurs and improves page performance.

// Set immediate argument to true to trigger function first
document.addEventListener('scroll', debounce(logScroll, 500, true));
Enter fullscreen mode Exit fullscreen mode

Like much of the techniques outlined in this series, this debounce approach is a single tool for you to keep on hand and employ when needed. Sometimes, your purposes might be better served by a throttle approach rather than debounce, and sometimes more thoughtful optimizations will be needed to boost performance of your creations. Try it out and see where it works best!

Top comments (0)

Visualizing Promises and Async/Await 🤯

async await

☝️ Check out this all-time classic DEV post