Introduction
In the fast-paced world of web development, performance and efficiency are paramount. When building interactive applications, it's common to encounter events that fire frequently, such as window resizing, scrolling, or user input. Without proper handling, these events can lead to performance issues and a poor user experience. This is where debounce and throttle come into play.
Debounce and throttle are two essential techniques that help optimize event handling by controlling the rate at which functions are executed. While they both serve to improve performance, they do so in distinct ways, each suited to different scenarios.
In this blog, we'll dive deep into the concepts of debounce and throttle, explore their differences, and provide practical examples to help you implement these techniques in your JavaScript projects.
What is Throttle?
Throttle is a technique used in JavaScript to control the rate at which a function is executed. When an event occurs frequently, such as scrolling, resizing, or mouse movements, invoking a function for every single event can lead to performance bottlenecks.
Throttling helps manage this by ensuring that the function is only called at most once in a specified period, regardless of how many times the event is triggered.
Understanding the use case for throttle
Let's understand throttle with an example.
Let's assume you have a webpage like this.
You can type your input into search box & grid will render matching results.
Additionally, you can click the Refresh button to refresh grid data. This will trigger GET API call.
Now what if user keeps on clicking on Refresh button? It will trigger countless API calls & will lead to bad performance of webpage. At one point it may even crash.
This is where we can use throttle. Using throttle, we can limit the number of times the Refresh function is called.
This is how throttle looks like,
Once user clicks Refresh button, we call the refresh function & then block the refresh function from getting called again until certain time has passed let's say 300ms.
This way we can reduce the network calls & improve the performance.
How does throttle function look like?
Let's try to write our own throttle function.
function throttle(functionToCall, limit = 200){
// Initially we want to call the `functionToCall`
// Hence default value is set to true.
let hasIntervalPassed = true;
return function(...arguments){
const context = this;
const args = arguments;
// Once the function is called,
// we now want to block the function call & set the limit
if(hasIntervalPassed){
// We're using `apply` because
// 1] It can access context
// 2] Multiple arguments can be passed easily.
functionToCall.apply(context, args);
hasIntervalPassed = false;
setTimeout(function(){
// Once the interval has passed,
// we want to allow `functionToCall` to be called.
hasIntervalPassed = true;
}, limit);
}
}
}
// Let's assume our button has id `my-custom-button`
const myButton = document.getElementById('my-custom-button');
function buttonClick (event) {
// handle api call here
}
myButton.addEventListener('click', throttle(function(event) {
buttonClick(event);
}, 500))
This covers a very basic implementation of throttle function.
If you wish to use a more professional version, checkout Lodash Throttle.
It's a production ready & well-tested function.
What is Debounce?
Debounce is a technique used in JavaScript to limit the rate at which a function is executed. When an event triggers frequently, debounce ensures that the function runs only after a specified period of inactivity. This means the function will only be called once the event has stopped firing for a certain amount of time.
Understanding the use case for debounce
Lets take the same webpage as above
Let's say you have this webpage.
You want to search some data in the grid.
Let's assume a Search API call is invoked when anything is typed into search input. Now do we need to call Search API when for every keystroke? Will anything significant be captured in the search input per keystroke?
Invoking Search API per keystroke will have lots of network calls. This will put a lot of stress on your application. It may even crash.
With debounce we wait for a certain interval of time before we make the function call.
This way we even give user enough time to type something significant & this might even increase the accuracy of Search API results.
This is how debounce looks like,
We wait till user has interacted with component. When the time interval passes without any user activity, call the function.
If user interacts with the component before the interval has passed, we reset the interval & continue to wait until interval passes without any user activity.
How does debounce function look like?
Let's try to write our own debounce function.
function debounce(functionToCall, interval = 200){
let timeOutId;
return function(...arguments){
// We keep storing all the arguments when user is interacting
// When the user interaction stops for mentioned interval,
// We call the function with these arguments
const context = this;
const args = arguments;
// If the user keeps interacting before interval has passed,
// We reset the interval
clearTimeout(timeOutId);
// If no user activity is detected for mentioned interval,
// We call the function
timeOutId = setTimeout(() => {
functionToCall.apply(context, args);
},interval)
};
}
// Let's assume our search field has id `my-search-field`
const mySearchField = document.getElementById('my-search-field');
function handleSearch (event) {
// handle api call here
}
mySearchField.addEventListener('input', debounce(function(event) {
handleSearch(event);
}, 2000));
This covers a very basic implementation of debounce function.
If you wish to use a more professional version, checkout Lodash Debounce.
It's a production ready & well-tested function.
That's it folks! Hope you enjoyed the learning 😄
Go ahead! Leverage throttle & debounce in your code 🥳
Top comments (16)
Thanks
that was nice. i heard about debounce and throttle and it is clear to me now
Thanks Soumesh! Happy to contribute😄
Combining debounce and throttle can be most helpful to get a better user experience. Debounce events to reduce workload, but not too much to block the execution. See an implementation [here]{dev.to/efpage/better-event-throttl...}
Ohh! I'll surely checkout. Thanks 😄
Your "throttle" function will be error in case of multiple clicks on the button at the same time.
Because it will run a setTimeout every time you click.
To avoid this error, we should put the setTimeout function in the condition hasIntervalPassed is true.
This is my opinion.
And thank for your post.
@btphuong2017 Thanks for your keen observation 😄. I've corrected the code.
Nice article! You should update your code blocks to include the language, so it adds syntax highlighting. ‘’’javascript
Ohh right!! I missed it! Thanks Matt😄
New knowledge obtained, thank you
Thanks!! Happy to contribute 😄
Awesome article. I wish you come up with more like this.
Thank you so much! @ajaymanikanta1123 😄 I'll definitely try to write more articles.
thanks for this
Thanks a lot; I just finished reading JavaScript Event module but I did not see such an important issue. I love it.
Thanks @george_nwosu_c55f8d86fad0 😄. Glad to know😇