防抖和节流
防抖
触发高频事件后 n 秒内函数只会执行一次,如果 n 秒内高频事件再次被触发,则重新计算时间。
例如公交车司机,手里面有一个计时器,如果三分钟之内没有人再上车,他就发车。司机第一次按下了计时器,结果到了一分半钟的时候,有一个乘客上车了,此时他就把手里的计时器清零,然后再等待三分钟,结果又过了两分钟,又上来了一个乘客,司机不得不再次把计时器清零,就一直这么持续下去,直到计时器在三分钟之内没有乘客再上车,那么司机就可以发车了。
实现思路:每次触发事件时都取消之前的延时调用方法。
function debounce(func, delay) {
let timer // 创建一个标记用来存放定时器的返回值
return function (...args) {
if (timer) {
clearTimeout(timer) //如果用户再次输入,则把前一个 setTimeout clear 掉
}
timer = setTimeout(() => {
func.apply(this, args) //利用apply保证我们的this指向我们调用的那个对象
}, delay)
// 然后又创建一个新的 setTimeout, 这样就能保证输入字符后的 delay 间隔内如果还有字符输入的话,就不会执行 fnnc 函数
}
}
防抖的应用:防抖最佳的应用就是用在处理用户输入,有个输入框,输入之后会调用接口,获取联想词。但是,因为频繁调用接口不太好,所以我们在代码中使用防抖功能,只有在用户输入完毕的一段时间后,才会调用接口,出现联想词。
节流
高频事件触发,但在 n 秒内只会执行一次,所以节流会稀释函数的执行频率。
实现思路:每次触发事件时都判断当前是否有等待执行的延时函数
function throttle(func, delay) {
let canRun = true //通过闭包保存一个标记
return function (...args) {
if (!canRun) return //在函数开头判断标志是否为 true,不为 true 则中断函数
canRun = false //将canRun 设置为 false,防止执行之前再被执行
setTimeout(() => {
// 将外部传入的函数的执行放在setTimeout中
func.apply(this, args)
// 执行完事件(比如调用完接口)之后,重新将这个标志设置为 true。当定时器没有执行的时候标记永远是false,在开头被return掉
canRun = true
}, delay)
}
}
节流的应用:
- 懒加载要监听计算滚动条的位置,使用节流按一定时间的频率获取。
- 用户点击提交按钮,假设我们知道接口大致的返回时间的情况下,我们使用节流,只允许一定时间内点击一次。