什么是防抖节流
函数防抖 是指在一定时间内,在动作被连续频繁触发的情况下,动作只会被执行一次,也就是说当调用动作过n毫秒后,才会执行该动作,若在这n毫秒内又调用此动作则将重新计算执行时间,所以短时间内的连续动作永远只会触发一次。
函数节流 对于短时间内大量触发同一事件(滚动事件、输入框实时搜索),那么在函数执行一次之后,该函数在指定的时间期限内不再工作,直至过了这段时间才重新生效
函数节流(throttle) 与 函数防抖(debounce) 都是为了限制函数的执行频次,以优化函数触发频率过高导致的响应速度跟不上触发频率,出现延迟,假死或卡顿的现象。
简单记忆 :前节流,后防抖
前节流: 同一个函数,第一次触发执行后开始算时间(自己定义的间隔时长),间隔时间结束前不会在执行这个函数
节流是将多次执行变为每隔一段时间执行一次
后防抖: 同一个函数,第一次触发后开始算时间(自己定义的间隔时长),间隔时间内如果再次触发则重新计算剩余时间,直到最后一次触发的间隔时间计算结束后,才第一次执行这个函数
防抖是将多次执行变成最后一次执行
使用场景
防抖
- 短信验证码
- 滚动事件
- 表单重复提交
- 页面 resize 事件
- input 事件(当然也可以用节流,实现输入框实时搜索)
节流
- scroll 事件,单位时间后计算一次滚动位置
- input 事件
- 播放事件,计算进度条
函数封装
节流
// 节流 定时器 + 时间戳
export let throttle = (func: any, delay: number = 200) => {
// 第一次触发时间戳
let startTime = Date.now();
return (...args: any[]) => {
// 如果不是剪头函数可以使用arguments获取参数,这样就不用写形参了考虑形参个数了
// let args = arguments;
// 再次触发时间
let curTime = Date.now();
// 间隔时间 = 延迟的时间 - (再次触发时间戳 - 第一次触发时间戳)
let interval = delay - (curTime - startTime);
if (interval <= 0) {
// 重新计算开始时间
startTime = Date.now();
return func(...args);
}
};
};
防抖
// 防抖
export let debounce = (fn: Function, delay: number = 200) => {
let timer: any;
// 闭包
return (...args: any[]) => {
// 如果不是剪头函数可以使用arguments获取参数,这样就不用写形参了考虑形参个数了
// let args = arguments;
// 判断还在定时,说明当前正在一个计时过程中,并且又触发了相同事件。所以要取消当前的计时,重新开始计时
if (timer) {
clearTimeout(timer);
}
timer = setTimeout(() => {
timer = null;
return fn(...args);
}, delay);
};
};