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:
- Any existing timeout gets cleared.
- 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.
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.
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)
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.
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.
No comments so far
Curious about this topic? Continue your journey with these coding courses: