What is debounce and throttle?#
Essentially, they are means of optimizing the execution of high-frequency code.
In the process of front-end development, we often need to bind some continuously triggered events, such as resize
, scroll
, keypress
, mousemove
, etc. When these events are triggered, the bound callback functions are constantly called, which greatly wastes resources and reduces front-end performance. However, sometimes we do not want to execute the function so frequently during the continuous triggering of events. In this case, debounce and throttle are good solutions.
Definitions#
- Debounce: After a high-frequency event is triggered, the function will only be executed once within n seconds. If the high-frequency event is triggered again within n seconds, the time will be recalculated.
- Throttle: The high-frequency event is triggered, but the function will only be executed once within n seconds, so throttle dilutes the execution frequency of the function.
What are the differences?#
Similarities:
- Both can be implemented using
setTimeout
. - The purpose is to reduce the frequency of callback execution and save computing resources.
Differences:
- Debounce processes the callback after a continuous operation ends, using
clearTimeout
andsetTimeout
. - Throttle executes the callback only once within a certain period of time during a continuous operation, and is used to improve performance in events with high frequency.
- Debounce only triggers the last event, while throttle triggers the next event only after the previous request is successfully responded to.
How to implement?#
Debounce: Cancel the previous delayed invocation method every time an event is triggered#
function debounce(fn) {
// Create a flag to store the return value of the timer
let timeout = null;
return function () {
// Clear the previous setTimeout whenever the user inputs
clearTimeout(timeout);
// Then create a new setTimeout, so that if there is still input within the interval after the character is entered, the fn function will not be executed
timeout = setTimeout(() => {
fn.apply(this, arguments);
}, 500);
};
}
function sayHi() {
console.log('Debounce success');
}
var inp = document.getElementById('inp');
inp.addEventListener('input', debounce(sayHi)); // Debounce
Throttle: Check if there is a delayed function waiting to be executed every time an event is triggered#
function throttle(fn) {
// Use closure to save a flag
let canRun = true;
return function () {
// Return if the flag is not true at the beginning of the function
if (!canRun) return;
// Immediately set it to false
canRun = false;
// Put the execution of the function passed in from the outside into setTimeout
setTimeout(() => {
fn.apply(this, arguments);
// Finally, after the execution of setTimeout is completed, set the flag to true (key) to indicate that the next loop can be executed.
// When the timer is not executed, the flag is always false and is returned at the beginning
canRun = true;
}, 500);
};
}
function sayHi(e) {
console.log(e.target.innerWidth, e.target.innerHeight);
}
window.addEventListener('resize', throttle(sayHi));
Application scenarios#
Debounce#
- Buttons such as login and sending messages should avoid users clicking too fast, resulting in multiple requests being sent. Debounce is needed in this case.
- When adjusting the browser window size, if the resize frequency is too high, causing excessive calculations, debounce is used to achieve the desired result in one go.
- Real-time saving in text editors, saving after one second of no further changes.
Throttle#
- Scroll events, calculate position information every second, etc.
- Browser playback events, calculate progress information every second, etc.
- Real-time search and send requests to display dropdown lists in input boxes, send requests every second (can also be implemented with debounce).