1、防抖
触发高频事件后n秒内函数只会执行一次,如果n秒内,再次被触发,则重新计算时间;
短时间内, 同一事件被频繁触发,防抖保证只能有一次触发,会执行一次函数(生效), 前面N多次触发,都会被忽略
在开发过程中,根据不同的场景, 来决定是否需要立即执行;
/**
* @desc 函数防抖
* @param func 函数
* @param waitTime 延迟执行毫秒数
* @param immediate 是否立即执行(true/false)
*/
const debounce = (func, waitTime, immediate) => {
let timeout = null;
return () => {
let context = this;
let args = arguments;
if (timeout) clearTimeout(timeout);
if (immediate) {
var callNow = !timeout;
timeout = setTimeout(() => {
timeout = null;
}, waitTime)
if (callNow) func.apply(context, args)
} else {
timeout = setTimeout(function(){
func.apply(context, args)
}, waitTime);
}
}
}
const doDebounce = () => {
console.log('执行防抖');
}
debounce(doDebounce, 1000, false);
2、节流
高频事件触发,但在n秒内只会执行一次,所以节流会稀释函数的执行频率
在指定时间内只执行一次
/**
* @desc 函数节流
* @param func 函数
* @param waitTime 延迟执行毫秒数
* @param type
* 1 函数触发是在时间段内开始的时候, 在持续触发事件的过程中,函数会立即执行,并且每 1s 执行一次;
* 2 函数触发是在时间段内结束的时候, 在持续触发事件的过程中,函数不会立即执行,并且每 1s 执行一次,在停止触发事件后,函数还会再执行一次。
*/
const throttle = (func, waitTime ,type) => {
if (type===1){
let previous = 0;
} else if(type===2){
let timeout = null;
}
return () => {
let context = this;
let args = arguments;
if (type === 1){
let now = Date.now();
if (now - previous > waitTime) {
func.apply(context, args);
previous = now;
}
} else if(type === 2){
if (!timeout) {
timeout = setTimeout(() => {
timeout = null;
func.apply(context, args)
}, waitTime)
}
}
}
}
3、使用场景
防抖
- 当用户快速输入关键字搜索时,浏览器每隔500ms才会执行事件处理函数。这意味着,当用户快速输入的过程中,浏览器会不断重新计算执行事件的时间,直到500ms内,用户停止输入,才真正的执行事件处理函数。
- 这样做的好处是,防止大量不必要的事件触发,能优化性能。
节流
- 鼠标不断触发某事件时,如点击,只在单位事件内触发一次;
- 懒加载时要监听计算滚动条的位置,但不必要每次滑动都触发,可以降低计算频率,而不必要浪费CPU资源.;
总结
函数防抖(debounce)、函数节流(throttle),都是为了限制函数的执行频次,优化函数触发频率过高,而导致的响应速度跟不上触发频率,出现延迟,假死或卡顿的现象。