paint-brush
Eliminating Event Storms With Debouncing in JavaScriptby@marat
393 reads
393 reads

Eliminating Event Storms With Debouncing in JavaScript

by MaratJanuary 12th, 2023
Read on Terminal Reader
Read this story w/o Javascript
tldt arrow

Too Long; Didn't Read

Debounce is a higher-order function that takes 2 arguments: a main function and a timer. The purpose of the debouncing is to reduce the load on the browser by reducing the number of calls. For instance, if you set a debounce with a time of 100 ms to the `onscroll` event, then the function will be executed 100 ms after the scroll stops.
featured image - Eliminating Event Storms With Debouncing in JavaScript
Marat HackerNoon profile picture

In my previous article, I talked about throttling. This time, we will look at the debounce function and how it differs from throttling.

How to Use Debounce

Using debounce, the function will be executed only when a certain amount of time has passed since the last function call. The delay starts again with each new call.


For instance, if you set a debounce with a time of 100 ms to the onscroll event, then the function will be executed 100 ms after the scroll stops.


Another example of using debounce is sending AJAX requests to the server. Let's say there is a search field on the website and you need to send requests after the user enters a request, and at the same time, limit the sending of requests for each character pressed.


In this case, you can use debounce, and set the time interval after which the request will take place. For example, by setting 1000 ms, the request will occur only after the pressing speed has exceeded 1 second.


Schematically, it can be displayed in the following way:

Debouncing schematically


Just to compare, I’ll duplicate the throttling scheme from the previous article:

Throttling schematically


Many JavaScript libraries such as lodash, underscore, and rxjs provide debounce and throttle methods with various additional features. Below you can view an implementation of the debounce method:


const debounce = function debounce(fn, time) {
    let timeout = null;
    return function () {
        const context = this;
        const args = arguments;
        const later = () => {
            fn.call(context, ...args);
            clearTimeout(timeout);
            timeout = null;
        }
        clearTimeout(timeout)
        timeout = setTimeout(later, time);
    }
}


Debounce is a higher-order function that takes 2 arguments: a main function and a timer. You can learn more about higher-order functions in our series of articles about functional programming.


Each function call updates the timer. When the timer expires, the function is executed. For instance, let's write a simple window resize event handler, just like we did in the throttling article:


const handleResize = () => {
    const { innerHeigh, innerWidth } = window;
    console.log({ innerHeigh, innerWidth });
}

window.addEventListener('resize', handleResize)


Let's wrap the handler in the debounce function, and then make sure that the function is called only once:


const handleResize = () => {
    const { innerHeigh, innerWidth } = window;
    console.log({ innerHeigh, innerWidth });
}

const handleResizeDebounced = debounce(handleResize, 500);
 
window.addEventListener('resize', handleResizeDebounced);


The above example makes almost no sense in practice. The main thing is to understand the logic, and that the purpose of the debounce and throttle functions are to reduce the load on the browser by reducing the number of calls.

Debounce Use Cases

General debounce use cases are as follows:


Browser window resizing: Let's say that when resizing the browser window, some dynamic elements are redrawn, which ends up with complex calculations in many cases, so here we can take advantage of both throttle and debounce.


The debounce optimization will be more significant since the function call will only take place when the user has finished resizing the browser window; while with throttle, the passed function will fire in the process of resizing after a given timeout.


Reducing the number of AJAX requests: For instance, when entering a request in a search field, use the debounce function in the corresponding event handler with a delay of 200 milliseconds.


Thus, the request will not be sent to the server after each letter is entered but will be sent once after the user stops entering a query and only after 200 milliseconds.

Choosing a Function Depends on the Task

  1. If you need the function to be executed at a certain frequency during any action (resize, scroll, keydown), use throttle


  2. If you need to call a function at the end of some action, it’s better to use debounce


  3. If a function call is required at the beginning of an action, then we use debounce with an additional immediate call parameter

Conclusion

This article describes how the throttle and debounce functions work and how to use them.


You may not fully understand the logic of the throttle and debounce functions at first, but it will be a huge advantage to use these functions during development, as this reduces the load on the browser, and therefore on the user's device.