In this article, we will discuss advanced and important topics of JavaScript - Debounce, and Throttle. These topics are asked in many JS interviews so I am going to discuss them in detail with examples so that you will ace these questions in your next interview!
Why it's needed?
Debounce and Throttle are the two techniques used to improve browser performance by limiting the rate of function calls. There might be a case where you have a heavy performant function that is called frequently which is time-consuming and subsequently will affect the performance of the browser. In such a scenario debounce and throttle are saviors.
Let's see them one by one!
Debouncing
In this technique, the rate of function calls is limited by delaying the execution of the function until a specified time to avoid unnecessary CPU cycles, and API calls and to improve the performance.
Let's understand this by a popular example which is the search bar. Whenever a user types something in the search bar it makes an API call. Suppose for an e-commerce use-case, when a user searches for a specific product one can see multiple suggestions popped up. So, what happening here is for every letter that is typed, there will be an API call.
Suppose a user types "Macbook pro" leading to 11 API calls to get the results. This is not an ideal way so to reduce the count of API calls debounce come into the picture.
First, let's see how it will look without debounce implementation.
If you see the API is being called on each character typed by the user and this will affect the performance of your application. With debounce, we can optimize the API calls by waiting for a certain amount of time before firing the next API call.
If you see we have optimized the API calls and the next API call will be triggered only after exceeding the given limit of time. i.e if the difference between two keypress events is greater than the limit(given by the user) then only make the next API call. So this way we can prevent unnecessary API calls and improve the performance of the application.
Implementation of debounce function from scratch
function debounce(cb,delay){
let context = this; //makes the context always the same as in cb(ref for cb)
let timer;
return function(...args){
//clears the timer before call setTimeout(helps to restrict multiply timer instances)
clearTimeout(timer)
timer = setTimeout(()=>{
// Call the original function with apply
// apply lets you define the 'this' object as well as the arguments
//(both captured before setTimeout)
cb.apply(context,args)
},delay)
}
}
Here is our debounce function from scratch, it takes two arguments - callback function(cb) and delay and returns another function.
context - it refers to this i.e it will keep a check that the environment where the function is running is correct and that the same function is called with the same arguments if any.
args - allows the debounce function to take any number of parameters to pass to the callback.
- firstly, we clear the timer if it's already initialized.
- We assign setTimeout to the timer which will run only after the delay expires.
- So that when the user types again the previously initialized timer will be cleared out and a new setTimeout will run with a new timer.
- If a keystroke occurs between the time(delay) then the timer will be cleared out preventing the immediate API calls.
- If the user stops typing then the function will run after the given delay and then call the API.
This is how debounce works in the background!
Throttling
In this technique, the function call is made at intervals of the specified amount of time i.e. the attached function is called only once in the given interval of time no matter how many times a user fires the event. The next function call will be triggered only after a certain time.
Let's understand by an example. Suppose there is a button that when clicked makes an API call to fetch some data. In this case, if the button is clicked n number of times the function will be triggered n times which is kind of absurd and leads to a performance drop.
This can be avoided if there is some limit set on the click event which can be achieved using the throttle.
First, let's see how it will look without throttle implementation.
If you see, that if the user clicks continuously the API will be called continuously which will affect the performance of your application. This can be handled by setting a click-limiter on the event with the help of the throttle function.
If you see, we have optimized the API calls such that even if the user continues to click the button only the first event will be triggered and all other events will be dropped until a specific interval of time.
Implementation of throttle function from scratch
const throttle = (func,limit)=>{
//made closure so that we don't need to initialize the flag again n again
let shouldTrigger=true; //added to restrict the func
return (...args)=>{
let context = this;
if(flag){
func.apply(context,args);
shouldTrigger=false;
setTimeout(()=>{
shouldTrigger=true;
},limit)
}
}
}
Here is our throttle function from scratch, it takes two arguments - function(func) and limit(time interval) and returns another function.
shouldTrigger - flag to restrict the function calls.
- First, we have set the flag to true so that the function will run on the first event
- The function will be called only when the flag is set to true. So on the first call, it will run the function.
- As soon as the function is executed, we are setting the flag to false so that there are no further function calls. Even if the user continues to click the events will be ignored because the flag is set to false.
- We are setting the flag to true only after the given limit is crossed. The next API will be called only after the limit(interval) is expired.
- All other events shot between the interval will be ignored hence, limiting the function calls.
So this is how throttle works underhood!
DEMO - This is a demo of debounce and throttle to make you understand better.
You can check it by yourself by visiting this link
Use Cases
Window resize operations cause various child elements to update themselves by resizing and re-organizing themselves. By throttling, you can delay the resize events and fire fewer of those resize events.
Use throttle on button click if you don't want the user to spam by frequently clicking the button.
In infinite scrolling, we can use throttling as we want to load new content after some interval of scrolling, not at every scrolling event.
In the case of searching for external data, wait until the end-user stops typing by using debounce.
We can use debounce on the mouse move event, if we are displaying the location coordinates of the mouse pointer, it is much better to show the coordinates once the user reached the desired location.
Summary
Debouncing is a technique where we can monitor the time delay of user action and once that delay reaches our predetermined threshold(delay) we can make the function call.
Throttling is a technique where we make the function call in a predetermined time interval irrespective of continuous user actions.
That's it for this article, I hope you found this article helpful and will help you in your next interview!!