Monday, May 3, 2021

How to Implement Debounce and Throttle with JavaScript

In JavaScript, whenever we’re attaching a performant-heavy function to an event listener, it's considered best practice to control how often the function is called. In this tutorial, we’ll take a look at how to implement debounce and throttle functions for regulating events.

It’s All About Performance

Performance is a major concern when building web pages, especially for sites which carry out animations and interactions. Event listeners are a common choice for implementing interactions with JavaScript as they are used to detect changes on a page and call functions according to those changes. It's important to ensure that event listener scripts are optimised for performance.

How do Event Listeners Impact Performance?

Let’s look at how often event listeners are called according to user actions. Carry out the corresponding events in the demo below to see the count:

Event listeners impact performance depending to the events they’re calling.

Let’s assume we have a function that’s responsible for adding new elements to the DOM and we call this function every time the user scrolls. As we’ve seen in the demo, the scroll event listener can be called for every pixel the user scrolls the screen.

Adding elements to the DOM cause reflows, which is the browser’s way of calculating the placement for new elements. Reflows are done in a cascading manner so changing the reflow of one element will cause a change in all subsequent elements and part or all of the document to be re-rendered. These calculations can affect user speed and slow down your page. You can read more on how reflows and repaints affect performance in this article.

Whenever we’re attaching a performant-heavy function to an event listener, it’s considered best practice to control how often the function is called.

Debounce and Throttle are two methods for optimising performance of scripts by controlling how often an event is called.

Debounce vs. Throttle

The major difference between debouncing and throttling is that debounce calls a function when a user hasn’t carried out an event in a specific amount of time, while throttle calls a function at intervals of a specified amount of time while the user is carrying out an event

For example, if we debounce a scroll function with a timer of 250ms (milliseconds), the function is only called if the user hasn’t scrolled in 250ms. If we throttle a scroll function with a timer of 250ms, the function is called every 250ms while the user is scrolling.

This demo provides a visual demonstration of the example above:

Debounce Function With Vanilla JavaScript

Let’s expand more on how the concept of debouncing works.

We can think of it as a wait-and-see function. When we debounce a function, we wait to see if the user carries out an action in a specified amount of time and if not, we’ll run the function. Now let’s convert that to logic.

  1. Initialise a timer variable that controls when to run a callback function
  2. Reset the timer function every time the user starts an action

Here’s what the logic implementation looks like:

In this code, we’ve initialised a timer variable called debounceTimer that controls a setTimeout method. This setTimeout method is what’s responsible for calling the function callback after the specified parameter time.

Inside our debounce function, we first clear the debounceTimer function every time the debounce function is called. This is what ensures that the callback function isn’t called until the time has been exhausted. If we set out debounce function inside a scroll event listener, the debounceTimer is reset by window.clearTimeout every time the user scrolls.

Use Cases for Debounce

Debouncing is a good method for controlling events that require sporadic user actions such as typing in an input field or clicking a button. In the case of a search bar that makes API calls according to user input, implementing a debounce is a good way to reduce the number of calls made to the API.

In this demo, we’ve debounced the user input to only return the input value if the user hasn’t typed anything in 500ms:

We can write the code for the above demo like this:

Implement a Throttle Function With Vanilla JavaScript

We can think of throttle as a minimizing function; it minimizes the number of calls made within a certain time interval.

Defining the logic for a throttle, we have:

  1. Initialize a variable to detect if the function has been called within the specified time
  2. If the function has been called, pause the throttle function
  3. If the function hasn’t been called or is done running in the interval, rerun the throttle function

We can write this in JavaScript as:

Here’s a breakdown of what’s happening:

  1. throttlePause is initially undefined, so the function moves on to the next line.
  2. We set throttlePause to true for the next iteration. If the throttle function is called again before setTimer is done, the function returns undefined.
  3. setTimeout starts a timer to run the function. The timer runs asynchronously while the throttle function is being called so it won’t be affected by the throttle function being called again.
  4. Once the callback has been run, it sets throttlePause to false so the throttle function can loop.

Use Cases for Throttle

Throttle is useful for cases where the user is carrying out a smooth or continuous event such as scrolling or resizing. In the event of animating elements based on their scroll position or handling an infinite scroll page, we can use throttle to control how often the scroll handler is called.

In this demo, we’ve set a throttle function on a scroll event listener:

The code for the above demo looks like this:

Conclusion

Now you should have a better understanding of the concepts and differences between throttle and debounce. We’ve also explored the logical approaches and code implementation of both methods so you can apply them to real life situations in order to optimize the performance of your scripts.

Learn More About Front-end JavaScript

From beginner concepts, to practical projects, we have you covered:

No comments:

Post a Comment