防抖和节流

168 阅读3分钟

来,先说概念:

防抖:

防抖函数指的是某个函数在某段时间内,无论触发了多少次回调,都只执行最后一次。假如我们设置了一个等待时间 3 秒的函数,在这 3 秒内如果遇到函数调用请求就重新计时 3 秒,直至新的 3 秒内没有函数调用请求,此时执行函数,不然就以此类推重新计时。

触发高频事件后n秒内函数只会执行一次,如果n秒内高频事件再次被触发,则重新计算时间。

节流:

函数节流指的是某个函数在一定时间间隔内(例如 3 秒)只执行一次,在这 3 秒内 无视后来产生的函数调用请求,也不会延长时间间隔。3 秒间隔结束后第一次遇到新的函数调用会触发执行,然后在这新的 3 秒内依旧无视后来产生的函数调用请求,以此类推。

高频事件触发,但在n秒内只会执行一次,所以节流会稀释高频函数的执行频率

相同点:在一定时间内,调用多次,但是只执行一次。

区别
防抖
节流
执行时间是否会延长新的调用进来,时间会延长,从最后一次调用开始计时不会,从第一次调用开始计时
最终执行的调用是最后一次是第一次

防抖:举一个这样的例子,也是真正的业务场景。


这是一个表单,我需要在银行卡号的onChange时间中取查询所属行,需求原因,不能放在onBlur中。

可以确定的是不能在每次的onChange事件中去查询,这就是一个典型的防抖的Demo。

直接来一个实现吧。

function debounce(fn, wait = 50) {    
// 通过闭包缓存一个定时器 id    let timer = null;    
// 将 debounce 处理结果当作函数返回    
// 触发事件回调时执行这个返回函数   
     return function(...args) {        // 如果已经设定过定时器就清空上一次的定时器        
        if (timer) clearTimeout(timer)        // 开始设定一个新的定时器,定时器结束后执行传入的函数 fn        
        timer = setTimeout(() => {           
             fn.apply(this, args)        
        }, wait)    
}}// DEMO
const betterFn = debounce(() => console.log('fn 防抖执行了'), 1000)
function debounce(fn, wait = 50) {
// 通过闭包缓存一个定时器 id
let timer = null;
// 将 debounce 处理结果当作函数返回
// 触发事件回调时执行这个返回函数
return function(...args) {
// 如果已经设定过定时器就清空上一次的定时器
if (timer) clearTimeout(timer)
// 开始设定一个新的定时器,定时器结束后执行传入的函数 fn
timer = setTimeout(() => {
fn.apply(this, args)
}, wait)
}
}
// DEMO
// 执行 debounce 函数返回新函数
const betterFn = debounce(() => console.log('fn 防抖执行了'), 1000)
// 停止滑动 1 秒后执行函数 () => console.log('fn 防抖执行了')
document.addEventListener('scroll', betterFn)


节流函数:

// wait 是时间间隔
const throttle = (fn, wait = 50) => {
// 上一次执行 fn 的时间
let previous = 0
// 将 throttle 处理结果当作函数返回
return function(...args) {
// 获取当前时间,转换成时间戳,单位毫秒
let now = +new Date()
// 将当前时间和上一次执行函数的时间进行对比
// 大于等待时间就把 previous 设置为当前时间并执行函数 fn
if (now - previous > wait) {
previous = now
fn.apply(this, args)
}
}
}
// 执行 throttle 函数返回新函数
const betterFn = throttle(() => console.log('fn 函数执行了'), 1000)
// 每 10 毫秒执行一次 betterFn 函数,但是只有时间差大于 1000 时才会执行 fn
setInterval(betterFn, 10)