实际上对于window和输入事件,实际需求大多为停止改变大小n毫秒后执行后续处理;而其他事件大多数的需求是以一定的频率执行后续处理,能够更好的起到性能优化的功能。针对这两种需求出现了debounce(函数去抖)和throttle(函数节流)两种方式
一、节流
比如mouseover,resize这种事件,每当有变化的时候,就会触发一次函数,这样很浪费资源。就比如一个持续流水的水龙头,水龙头开到最大的时候很浪费水资源,将水龙头开得小一点,让他每隔200毫秒流出一滴水,这样能源源不断的流出水而又不浪费。而节流就是每隔n的时间调用一次函数,而不是一触发事件就调用一次,这样就会减少资源浪费,一下代码是节流并且是利用闭包的原理实现的以及使用方法
let input = document.getElementById("input");
input.addEventListener("input", throttle((e) => {
console.log(input.value);
}))
function throttle(fn, time = 2000) {
// 定义上一次时间戳
let prev = new Date();
return function(...args) {
// 定义下一次时间戳
let now = new Date();
if (now - prev > time) {
// 时间差大于一秒触发函数
fn.apply(this, args);
// 更新时间戳
prev = now
}
}
}
二、防抖
A和B说话,A一直bbbbbb,当A持续说了一段时间的话后停止讲话,过了10秒之后,我们判定A讲完了,B开始回答A的话;如果10秒内A又继续讲话,那么我们判定A没讲完,B不响应,等A再次停止后,我们再次计算停止的时间,如果超过10秒B响应,如果没有则B不响应,就是指触发事件后n秒后才执行函数,如果在n秒内又触发了事件,则会重新计算函数执行时间
let input = document.getElementById("input");
input.addEventListener("input", debounce((e) => {
console.log(input.value);
}))
function debounce(fn, await = 3000) {
let timer;
return function(...args) {
if (timer) {
clearTimeout(timer);
}
timer = setTimeout(() => {
fn.apply(this, args);
}, await);
}
}