Before focusing on debounce
and throttle
methods, it’s important to know the setTimeout
function.
The setTimeout function allow us to execute a callback after a specific timer. The first parameter is the callback to execute, and the second one is the minimum duration when the callback has to be executed:
// Duration in milliseconds
setTimeout(callbackToExecute, waitInMilliseconds);
Here is an example usage:
function methodToDelay() {
console.log(
'I will be displayed after at least 1 second',
);
}
setTimeout(methodToDelay, 1000);
The debounce
function does not execute a callback as soon as the callback is called under a specified duration time.
For example, if we want to implement an input field that makes XHR calls to a backend API, to directly filter from the database. From scratch, a call will be made for
each keystroke. Most of the time, the user will type multiple letter that will result in multiple calls, but only the last will be useful. debouncing
the callback
will make the API call only when the user will not have type a character in less than 250ms for example.
The implementation is based on setTimeout
. The execution of the callback is delayed of a duration t, and if we want to execute again the callback before this period of
time, we will reset the timer.
function debounce(callback, waitTime) {
let timeoutId;
return function () {
clearTimeout(timeoutId);
timeoutId = setTimeout(() => {
callback.apply(this, arguments);
}, waitTime);
};
}
The throttle
function allow us to execute a callback periodically as soon this one is called.
For example, if we want to execute a process when the user is scrolling, if we only do a simple handler callback on event scroll
,
this one will be called hundreds of times or over. For performances, it’s not the best. So we will use a throttled
method to executes it
every 500ms for example and gives feedback to user (if it results to a visual process).
export default function throttle(callback, waitTime) {
let firstCallMade = false;
let recalled = false;
let latestContext;
let latestArguments;
return function () {
function recall() {
firstCallMade = true;
setTimeout(() => {
// If the function has been recalled, let's reexecute it
if (recalled) {
callback.apply(latestContext, latestArguments);
recall();
latestContext = undefined;
latestArguments = undefined;
recalled = false;
} else {
firstCallMade = false;
}
}, waitTime);
}
if (!firstCallMade) {
// It's the first call, let's execute the function
callback.apply(this, arguments);
recall();
} else {
// The callaback has been already called once
recalled = true;
latestContext = this;
latestArguments = arguments;
}
};
}
I have coded a little codesandbox to see the difference between this 2 methods. In this one there are:
- the method which is immediately called
- the method which is debounced
- the method which is throttled
Let’s go check this here .
You can find me on Twitter if you want to comment this post or just contact me. Feel free to buy me a coffee if you like the content and encourage me.