浅谈一下防抖和节流

174 阅读2分钟

一、什么是防抖,什么是节流

用我看过的一个综艺游戏来浅浅的区分一下。游戏中的嘉宾需要在一栋大楼中寻找各种卡片来完成任务。在任务的过程中要躲避黑衣人的逮捕,如果被逮捕到了就要被关进10分钟倒计时的小黑屋,每个小黑屋可以关多个嘉宾。我们想象一下这个画面:第一个嘉宾被黑衣人抓住关进小黑屋,10分钟倒计时开始,2分钟后,第二个嘉宾被关进小黑屋。倒计时有两种情况:1、倒计时重新被触发,从10分钟开始倒计时,那么第一个嘉宾被关12分钟,第二个嘉宾被关10分钟;2、倒计时从8分钟倒计时,那么第一个嘉宾被关10分钟,第二个嘉宾被关8分钟。情况1是防抖,情况2是节流。

二、防抖

防抖,就是防止抖动。当我们频繁的触发一个事件的时会引起不必要的性能损失,我们需要做的是让事件在停止触发后再触发,以此减少性能损失。以上面的游戏为例,关人进小黑屋是触发动作,频繁往里面关人时,不管关进去多少人,都以最后关进去那个人的时刻重新倒计时。

手写防抖代码

// (简单版本)
function debounce(fn, delay) {
    let timer = null;
    clearTimeout(timer); // 下次调用时会清除上次的timer, 然后重新延迟
    timer = setTimeout(function(){
        fn();
    }, delay);
} 

// (立即执行版本)
function debounce(fn, wait) {
    let timer = null
    return function () {
        let args = arguments
        let now = !timer
        timer && clearTimeout(timer)
        timer = setTimeout(() => {
            timer = null
        }, wait)
        if (now) {
            fn.apply(this, args)
        }
    }
}

防抖应用场景

防抖适合高频次的触发事件,但是只需要一次响应。比如搜索事件,用户每按下回车就调用接口,此时就可以用防抖,只在最后一次回车才调用接口。

三、节流

节流,就是控制事件高频次执行的次数。节流的作用是在一个单位时间内最多只能触发一次函数执行,如果这个单位时间内多次触发函数,只能有一次生效。以上面的游戏为例,10分钟就是一个时间单位,不管陆续关进去多少人,10分钟倒计时完毕,就会放人出来。

手写节流代码

//(定时器版本)
function throttle(fn, wait) {
    let timer = null
    return function () {
        let context = this
        let args = arguments
        if (!timer) {
            timer = setTimeout(() => {
                timer = null
                fn.apply(context, args)
            }, wait)
        }
    }
}

节流应用场景

节流适合大量事件按时间做平均分配触发。比如dom元素的拖拽,游戏中的刷新率等。

四、总结

防抖和节流能有效的减少浏览器的损耗,提高性能。用防抖还是节流还是要根据两者的原理和具体场景用。