The most complete and understandable principle, implementation and optimization of debounce and throttling
This article introduces the application and code implementation and optimization of debounce and throttling in detail. Among them, the function throttling implements the timer version and the timestamp version, and different versions are optimized.Read it patiently, you won't regret it
1. debounce
1.1 Definition
Debounce means that only when a function is not triggered again within n seconds, the function will actually be executed; if the function is triggered again within n seconds, the time will be recalculated, such as: when searching, when the user stops typing Only call the method to save request resources
1.2 Application scenarios
- Frequently enter content in the input box, search or submit information;
- Click the button frequently to trigger an event;
- Listen to the browser scroll event to complete the operation;
- The resize event when the user zooms the browser (triggered when the size of the browser window changes)
1.3 Implementation
Use a third-party library underscore
js handwritten
<body>
<input type="text">
<button id="cancel">cancel</button>
</body>
-
Basic implementation of debounce function
//Version 1, the basic implementation of the debounce function <script> let count = 0; const inpt = document. querySelector('input'); const foo = function (e) { console.log(`Send ${++count} request`, this, e); }; //Basic implementation of debounce function function myDebounce(fn, delay) { // 1. Define a timer let timer = null; const _debounce = function () { // cancel the last timer if (timer) clearTimeout(timer); // delay execution function timer = setTimeout(() => { //Modify the fn function this point and pass parameters, otherwise this points to window and the parameter is undefined fn.apply(this, arguments); }, delay); }; return_debounce; } //No debounce function is used // inpt.oninput = foo //Use debounce function inpt.oninput = myDebounce(foo, 800); </script>
No debounce function is used
Use debounce function
2.Optimize the debounce function: increase the effect of immediate execution
//Version 2, add immediate execution effect
function myDebounce2(fn, delay, immediate = false){
let timer = null
let isimmediate = false
const _debounce = function(){
if (timer) clearTimeout(timer)
// Determine whether to execute immediately
if(immediate && !isimmediate){
fn.apply(this,arguments)
isimmediate = true
}else{
//Pay attention to the arrow function, otherwise this points to window
timer = setTimeout(()=>{
fn.apply(this,arguments)
isimmediate = false
}, delay)
}
}
return_debounce
}
//use
inpt.oninput = myDebounce2(foo, 500, true);
3.Optimize the debounce function: increase the cancel effect (click the cancel button to cancel the sending request)
function myDebounce2(fn, delay, immediate = false) {
let timer = null;
let isimmediate = false;
const _debounce = function () {
if (timer) clearTimeout(timer);
// Determine whether to execute immediately
if (immediate && !isimmediate) {
fn.apply(this, arguments);
isimmediate = true;
} else {
//Pay attention to the arrow function, otherwise this points to window
timer = setTimeout(() => {
fn.apply(this, arguments);
isimmediate = false;
}, delay);
}
};
// Encapsulate cancel function
_debounce. cancel = function () {
clearTimeout(timer);
isimmediate = false;
};
return_debounce;
}
//use
let count = 0;
const inpt = document. querySelector('input');
const foo = function (e, a = '123') {
console.log(`Send ${++count} request`, this, e, a);
};
let debounceres = myDebounce2(foo, 800, false);
inpt.oninput = debounceres;
const cancelBtn = document. querySelector('#cancel');
cancelBtn. onclick = function () {
console.log('cancel request');
debounceres. cancel();
};
2. throttling
2.1 Definition
Throttling means that the js method will be executed once within a certain period of time, that is, the frequency of executing the function is fixed. Similar to a bus that runs every 10 minutes, no matter how many people are waiting at the bus stop within 10 minutes, it will leave on time as soon as 10 minutes arrive
2.2 Application scenarios
- Monitor page scrolling events;
- mouse move event;
- The user frequently clicks the button to operate;
- Some design in the game (such as how often the spaceship fires missiles)
2.3 js implementation
Timer version
The throttle function of the timer version has two characteristics:
- The first time will be executed after n seconds (the timer will not be triggered until the time is up)
- The throttling function will be executed once after the stop is triggered (because the function is delayed, its tasks have been added to the queue when the stop is triggered, so it will be executed once after the stop)
-
Basic implementation of throttling function
<script> function throttle(fn, delay){ let flag =true const _throttle = function(){ if(!flag) return flag = false setTimeout(()=>{ fn.apply(this, arguments) flag = true },delay) } return _throttle } </script>
-
Throttling optimization: increase cancellation request and immediate execution
//Timer version 2: cancel and execute immediately function throttle2(fn, delay = 500, immediate = false) { let flag = true let timer = null const _throttle = function () { if (!flag) return flag = false if (immediate) { console.log('immediately'); fn. apply(this, arguments) immediate = false flag = true } else{ timer = setTimeout(() => { fn. apply(this, arguments) flag = true immediate = false }, delay) } } _throttle. cancel = function () { if (timer) clearTimeout(timer) timer = null flag = true console.log('cancel request'); } return_throttle } //use const inpt = document. querySelector("input") const btn = document. querySelector('#cancel') let counter = 0 const inputChange = function (event) { console.log(`Send ${++counter} network request`, this, event) } let throttleres = throttle2(inputChange, 800, true) inpt.oninput = throttleres btn.onclick = function () { throttleres. cancel() }
Timestamp version
The timestamp version of the throttling function has two characteristics:
- It will be executed immediately after the trigger is started (because lastTime will be assigned a value of 0);
- It will not be executed after the trigger is stopped (because this function is a synchronous task, it will make a corresponding judgment when it is triggered, so there is no situation that it will be executed after the trigger is stopped).
-
Basic implementation of throttling function
//version 1: basic implementation function throttle(fn, interval) { //Record the last start time let lastTime = 0 const _throttle = function() { // Get the time when the current event is triggered const nowTime = new Date(). getTime() //Calculate whether the time interval between the current trigger time and the last time is greater than the delay time if (nowTime - lastTime >= interval) { fn.apply(this,arguments); //Retain the time of the last trigger lastTime = nowTime; } } return_throttle }
-
Throttling optimization: increase cancellation request and immediate execution
<body> <input type="text" /> <button id="cancel">Cancel</button> <script> //Version 2: Add cancellation request and whether to execute it immediately function throttle2(fn, interval, leading = true) { let lastTime = 0; const _throttle = function () { const nowTime = new Date(). getTime(); /* lastTime = 0 when calling for the first time, if lastTime === 0 is not added, lastTime = nowTime, and remainTime will not be less than 0 If you choose to execute immediately, there is no need to change If you choose not to execute immediately, set lastTime = nowTime, that is, interval-0, and wait for the interval delay time to trigger */ if (lastTime === 0 && !leading) lastTime = nowTime; //Triggered when the delay time is less than the interval time const remainTime = interval - (nowTime - lastTime); if (remainTime <= 0) { fn.apply(this, arguments); lastTime = nowTime; } } _throttle. cancel = function(){ lastTime = 0 console.log('cancel request'); } return_throttle } //use const inpt = document. querySelector('input'); const btn = document. querySelector('#cancel'); let counter = 0; const inputChange = function (event) { console.log(`Send ${++counter} request`, this, event); }; let throttleres = throttle2(inputChange, 1000, false); inpt.oninput = throttleres; btn.onclick = function () { throttleres. cancel(); }; </script>
Using non-immediate execution
3. The difference between debounce and throttling
Similar point: The emergence of debounce throttling is to solve the problem of performance consumption caused by frequent triggering of something, so that network requests can be sent under appropriate conditions
Difference: The difference between the two is that throttling is to do a certain thing at a fixed time, such as sending a request every n seconds; while debounce is only executed once when it is frequently triggered (the premise of both is frequent triggering )