Debouncing in JavaScript: How to delay a function execution

Debouncing in JavaScript: How to delay a function execution

Have you ever considered how well-optimized the search inputs in certain web applications are? Or, how does the web application handle user events so efficiently?

Web applications are extremely quick and efficient because of a crucial JavaScript technique called debouncing. Various developers employ this technique to boost the performance of web applications.

In this article, we will study what debouncing is and how it may significantly improve application performance. We will also look at how we can incorporate debouncing into our projects. In addition, we will look at numerous open-source libraries that provide debouncing utility functions.

What is Debouncing in JavaScript?

Have you ever clicked on a button on a website and thought it was loading the content a bit too slowly? Similarly, there is a brief delay between entering the search field and seeing the results. Developers use the debounce function to create this delay, which prevents unnecessary queries to the server.

Debouncing is a programming technique that limits the frequency with which a time-consuming (requiring more calculations) function gets called or executes a function only when necessary. Consider that you are a developer who is making a search bar. You would like to display recommendations only after the user has finished typing, not after each keypress. We use debouncing in JavaScript to enhance the efficiency of a web page.

How does Debouncing work?

Debouncing happens by starting a “delay” timer before executing a specific code section. And if for some reason, the identical procedure is repeated, then, instead of creating a queue of two similar events, we halt the previous process and concentrate on the current one’s execution.

Writing a Debouncing function in JavaScript.

Implementing a debouncing function using JavaScript is pretty straightforward. We can write a debouncing function in JavaScript as follows:

function debounce(callback, timer) {
  let timeoutId;

  return (...args) => {
    // save the current context (this)
    const context = this;

    // clear the existing timeout
    clearTimeout(timeoutId);

    // create a new timeout
    timeoutId = setTimeout(() => {
      callback.apply(context, args);
    }, timer);
  };
}Code language: JavaScript (javascript)

It’s not very simple to understand this function, primarily if you’re not used to functional programming. Let’s break down how our debouncing function operates piece by piece.

A callback function and a millisecond duration are the two arguments that our debounce method accepts. It returns another function which will be a debounced function.

The timeout variable is initialized on the function’s first line and executed only once. Even though debounce() gets called only once, we want to use the resulting debounced function repeatedly.

Two things happen each time the resulting debounced function gets called:

  1. Any existing timeout gets cleared.
  2. A new timeout is created based on the timer parameter that our debouncing method gets. We use the apply() method to call our callback function and provide it with the parameters we have when the timeout expires.

Setting a timeout yields a reference to that particular timeout. The reference Id gets stored inside our timeoutId variable. This variable remains in memory because it lies outside the scope of the function we wrapped. In this manner, a timeout gets cleared, and a new one gets created repeatedly until the user input stops for the duration specified by the timer parameter.

Pheww! That was a sophisticated process! However, it performs brilliantly. We should not worry too much about the expense of scheduling and clearing timeouts because it is a very rapid, low-memory process.

Examples

Now let’s talk about some instances when debouncing enhances application performance.

Search input fields

People frequently use debouncing in search input boxes. We call the API for each user’s keystroke when they enter some search term. It seriously affects performance. In this circumstance, debouncing is beneficial. This method delays or debounces the function that calls the API. Every keystroke will call the delayed function or the debounced function. In this instance, we make the API request only after the user stops typing for the time provided by the timer parameter that we send to the debounce function, even though we call the debounced function with each keystroke.

Let’s write some code to understand the process clearly.

To begin, we make a simple HTML file with a search input. The search input has a JavaScript event listener that runs a callback function with each key press.

<input type="text" id="input">Code language: HTML, XML (xml)
const input = document.getElementById('input');

input.addEventListener('input', callAPI);

function callAPI() {
    // Time consuming API call
    console.log('API called!');
}Code language: JavaScript (javascript)

Let’s run the code and see the output.

Search input field without debouncing
Search input field without debouncing

By typing five characters, you may see five logs on the console. At this stage, replace these logs with API requests. For each keystroke, we are making an API request. If we continue to utilize the same setup, the performance of the apps will be significantly reduced.

Instead of directly providing a callback function, we will give the event listener a debounced or delayed version of the callback function.

const debouncedCallAPI = debounce(callAPI, 500);

input.addEventListener('input', debouncedCallAPI);Code language: JavaScript (javascript)

Let’s now enter some search phrases and see the results.

Search input field with debouncing
Search input field with debouncing

Now, if we type five characters and wait for 500 milliseconds, we only see one log on the terminal. It indicates that the debounced callback function is operating perfectly.

Mouse events

Like search fields, we can employ debouncing for mouse events such as a “move” event. The mouse move event listeners track the mouse pointer’s position. It runs the callback provided every time the mouse moves. Let’s write an event listener for the mouse move event.

window.addEventListener('mousemove', mouseMove);

function mouseMove(e) {
    console.log(`Mouse moved to: ${e.clientX}, ${e.clientY}`)
}Code language: JavaScript (javascript)
Mouse move event without debouncing
Mouse move event without debouncing

As you can see, even if we shift the mouse cursor just a little, we still get plenty of logs on our terminal. This approach uses a lot of resources when we need to know the mouse pointer’s final location.

Instead of directly providing a callback function, we will give the event listener a debounced or delayed version of the callback function.

const debouncedMouseMove = debounce(mouseMove, 500);

window.addEventListener('mousemove', debouncedMouseMove);Code language: JavaScript (javascript)

Let’s now move the mouse pointer and see the results.

Mouse move event with debouncing
Mouse move event with debouncing

Now, even if we keep moving the mouse, we won’t get a log until we have stopped moving it for 500 milliseconds. It indicates that the debounced callback function is operating perfectly.

Implementations of debouncing in libraries

In this article, we built a debouncing function in JavaScript and applied it to delay specific events triggered by web applications. But if we don’t want to, we can choose not to employ our debouncing implementation in your applications. Their implementation is already present in frequently used JavaScript libraries. A few of them are JQuery, Lodash, etc.

Conclusion

In this article, we learned about debouncing and how it boosts the performance and speed of web applications. In addition, we created an implementation of the debouncing function and talked about how it worked piece by piece. We have examined a few use cases where debouncing greatly enhances web application performance by delaying time-consuming operation that saves a lot of resources. We also looked at a few libraries that offer debouncing function implementations as an alternative to using our code.

You can access all the source code using the following link:

Thank you so much for reading ?

Sharing is caring

Did you like what Varun Tiwari wrote? Thank them for their work by sharing it on social media.

0/10000

No comments so far