Table of contents
Hi , Zenith here .
In terms of top leading websites , performance is essential if you don't want to clog your servers . Such disasters begin from very basic events such as user search . And that's why debounce and throttle are here.
By the end of this guide , you'll have learnt two methods which can minimize the load on your servers and be performant too.
You can also watch the video , as it will provide some visual aid as well . ๐
Inside search bars
The search bar example is very common among many apps , thus the concept is useful here .
Take for an example the code below :
const inputElement = document.querySelector("input")
function HandleInput(event){
console.log("Now Fetching :",event.target.value)
}
inputElement.addEventListener("input",HandleInput)
As you can see , there are individual logs for each keystroke .Imagine if we replace that console.log with an actual fetch
request , then it would send a request for each input change . Suppose the user searches for the term car. The function would send the request as first c , then ca , then car and so on . That would be 4 requests to the server for just one search !
Debounce
Debounce is a method of delaying a continuously firing event such as user input or mouse movements until the user stops , and that's when the event is finally fired. Simply, it only triggers a function if it is not called again for a set period of time
So in the car example , the search will request only after when the user has stopped typing for a second or two.
A debounce function looks like this:
function Debounce(func,timeout = 1000){
let timer ;
return (...args) =>{
clearTimeout(timer)
timer = setTimeout(()=>{
func(...args)
},timeout)
}
}
A debounce function basically runs a callback function after set time but will cancel it if it is called again and will then set a new one. Thus only the latest callback runs and previous calls are ignored. That's one reason why we are using the setTimeout
here.
We first assign the timer
variable in the debounce function which will then be available to us for the next call too . Then we return the callback in an arrow function and also within a timeout . We first clear the timeout timer
and thus the previous call to this function is also cancelled . Then we set a new timeout and pass into it our callback with its arguments.
Now to address our above search issue , lets apply this into our search bar's logic :
function HandleInput(event){
console.log("Now Fetching :",event.target.value)
}
const DebounceInput = Debounce(HandleInput)
function Debounce(func,timeout = 1000){
let timer ;
return (...args) =>{
clearTimeout(timer)
timer = setTimeout(()=>{
func(...args)
},timeout)
}
}
inputElement.addEventListener("input",DebounceInput)
The only new part is the DebounceInput
which basically calls the Debounce function to which we pass the usual HandleInput function.
Now if you'd type car , the Debounce function will only trigger the callback after 1000ms if you've stopped typing completely .In that way only the latest search bar's input will be requested. ๐
Throttle
Throttle is a method in which a function is called at set intervals as long as the event for the function is being fired .Thus it also controls how many times a function is called in a specific period of time.
A throttle function looks like this:
function Throttle(func,timeout = 1000){
let shouldWait = false
return (...args) => {
if(shouldWait) return
func(...args)
shouldWait = true
setTimeout(() => {
shouldWait = false
}, timeout);
}
}
Similar to the Debounce function , but this has a shouldWait
Boolean variable . In the return function , we check if shouldWait
is true , if yes then return without triggering the callback . If no , then run the callback and make shouldWait
true, and in the timeout bring shouldWait
back to false . We simply are turning the Boolean to true and the callback doesn't fire as long as the timeout hasn't completed .
Let's replace debounce with this in to our search bar logic:
function HandleInput(event){
console.log("Now Fetching :",event.target.value)
}
const ThrottleInput = Throttle(HandleInput)
function Throttle(func,timeout = 1000){
let shouldWait = false
return (...args) => {
if(shouldWait) return
func(...args)
shouldWait = true
setTimeout(() => {
shouldWait = false
}, timeout);
}
}
inputElement.addEventListener("input",ThrottleInput)
We replace the DebounceInput
with ThrottleInput
and call Throttle in the same way as we did with Debounce .
Now if you'd type, the requests would be sending at a set interval , specifically 1 second . ๐
Wrapping up , now you should be able to apply these methods into your apps and make them performance efficient .
Thanks for reading and happy coding ๐ฉโ๐ป !