JavaScript: Anti-shake and throttling
One, anti-shake
-
Definition: The function will only be executed once within n seconds after the start of the high-frequency event. If the high-frequency event occurs again within n seconds, the time will be recalculated.
-
Implementation idea: Set a delayed call method every time an event is triggered, and cancel the previous delayed call method;
-
Disadvantage: If the event is triggered continuously within the specified time interval, the calling method will be continuously delayed.
// 简易版
function debounce(fn){
let timeout = null;
return function(){
clearTimeout(timeout);
timeout = setTimeout(()=>{
fn.apply(this,arguments);
},1000);
}
}
function handle(){
console.log(this);
}
window.onmousemove = debounce(handle);
- The simple version has a disadvantage: when the event is called, the this object always points to the window (because it is in the closure), so we can store the context in the closure first;
// 高级版
function debounce(func, wait, immediate){
var timeout, result;
let decounced = function(){
//改变内部this指向
let context = this;
let args = arguments;
clearTimeout(timeout);
if(immediate){
let callNow = !timeout;
timeout = setTimeout(() => {
timeout = null;
}, wait);
//表示立即执行
if(callNow) result = func.apply(context, args);
}else {
//不会立即执行
timeout = setTimeout(function(){
result = func.apply(context, args);
}, wait);
}
return result;
}
decounced.cancel = function(){
clearTimeout(timeout);
timeout = null;
}
return decounced;
}
function handle(){
console.log(this);
}
window.onmousemove = debounce(handle,1000,true);
Second, throttling
- Definition: triggered by a high-frequency event, but it will only be executed once in n seconds, over 100 million throttling will dilute the execution frequency of the function;
- Implementation idea: When the event is triggered, if there is currently a delay function waiting to be executed, return directly;
// 简易版
function throttle(fn){
let canRun = true;
return function(){
if(!canRun) return;
canRun = false;
setTimeout(()=>{
fn.apply(this,arguments);
canRun = true;
},1000);
}
}
function handle(){
console.log(Math.random());
}
window.onmousemove = throttle(handle);
- The same problem, the simplified version of this points to window;
// 高级版
// options传入一个对象,表示模式
//{
// leading : true/false,
// trailing : true/false
//}
function throttle(fn,wait,options){
let context,args,timeout,result;
let old = 0;
if(!options) options = {
};
let throttled = function(){
context = this;
args = arguments;
let later = function(){
old = new Date().valueOf();
timeout = null;
result = fn.apply(context,this);
}
let now = new Date().valueOf();
if(options.leading === false && !old){
old = now;
}
if(now - old > wait){
//头部执行
if(timeout){
clearTimeout(timeout);
timeout = null;
}
result = fn.apply(context,args);
old = now
}else if(!timeout && options.trailing !== false){
//尾部执行
timeout = setTimeout(later,wait);
}
return result;
}
throttled.cancel = function(){
clearTimeout(timeout);
old = 0;
timeout = context = args = null;
}
return throttled;
}
function handle(){
console.log(Math.random());
}
window.onmousemove = throttle(handle,1000,{
leading : true,
trailing : false
});
Three, the difference
- No matter how frequently the event is triggered, the throttling guarantees that the event function will be executed once within the specified time;
- Anti-shake only triggers a function in the last event;
Four, applicable scenarios
- Anti-shake
- The scroll event is triggered by scrolling, such as setting when the icon back to the top appears
- Enter the query in the search box, and search again when the user pauses after inputting (fuzzy search)
- Form validation, real-time detection when the user pauses after input
- Button submit event to prevent violent click from sending multiple requests
- Browser window zoom, resize event
- Throttling
- Realization of the drag and drop function of DOM elements
- shooting game
- Calculate the distance moved by the mouse
- Listen to scroll events