防抖(debounce)与节流(throttle)的区别

发布:elantion 日期:2020-11-28 阅读:446 评论:0

在写事件处理时,例如滚动事件,如果事件回调比较耗性能,为了不使页面卡顿,一些前辈经常会让我们写”防抖“,但有些人就说不对,应该用”节流“。刚开始看这两个概念时也不太好区分,它们究竟有什么区别呢?

节流 Throttle

日常生活中,水龙头出水太大了,就扭小一点,这种行为就叫节流。也就是说,我们限制每段时间的出水量。程序里的节流也差不多,主要是希望每一小段时间只执行一次,例如每100毫秒只执行一次。像下图:

|     x   |  x      |      x  | 
|  100ms  |   100ms |   100ms |

这里的x就是事件函数的执行,限制了每100ms只执行一次。具体的代码类似这样:

let isThrottling = false;
setInterval(() => isThrottling = true, 100);
window.onscroll = function() {
    if (isThrottling){
        return;
    }
    isThrottling = true;
    // heavy job
};

当然,这只是示例代码,实际场景需要适当做些修改,不过意思差不多就是这样。

防抖 Debounce

防抖意思就是事件函数执行完之后,等一小段时间才能再执行。同样的,我们希望事件函数执成完,等100ms后才能再次被执行,实现类似下图的情况:

|        | x |        |   x  |        | x |
| 100ms  |8ms|  100ms | 12ms |  100ms |4ms|

与节流不同,执行时间是不算进时间间隔的,简单来说,就是函数执行完之后必须要等上一段时间才能再次执行。
看看示例代码:

let isDebouncing = false;
window.onscroll = function() {
    if (isDebouncing){
        return;
    }
    isDebouncing = true;
    // heavy job start
    // ...
    // heavy job done
    setTimeout(() => isDebouncing = false, 100);
};

所以,如果事件函数执行非常耗时,例如超100ms,在节流模式下,函数的执行可能会横跨两个100ms,但在防抖模式下就不会有这种情况了。

复杂场景

上面都是比较简单的场景,主要是方便理解,但现实中有许多比较复杂的场景,例如我们需要事件触发时,是先执行函数再防抖,还是先防抖再执行;节流模式下希望某段时间执行两次到多次,是先执行还是先节流;等等。这里就不展开了,大家有兴趣可以阅读下面文章:

函数防抖和节流