浅谈Debounce 与 Throttle

18,322 阅读3分钟
debounce 与 throttle 是开发中常用的高阶函数,作用都是为了防止函数被高频调用,换句话说就是,用来控制某个函数在一定时间内执行多少次。

使用场景:比如绑定响应鼠标移动、窗口大小调整、滚屏等事件时,绑定的函数触发的频率会很频繁。若稍处理函数微复杂,需要较多的运算执行时间和资源,往往会出现延迟,甚至导致假死或者卡顿感。为了优化性能,这时就很有必要使用debouncethrottle了。

由于debouncethrottle两个函数的作用相同,且调用方法和参数都相同,这让我们很容易弄混。今天就来谈谈debouncethrottle的用法与差异。
下面先看看lodash中的_.debounce()_.throttle()
_.debounce(func, [wait=0], [options={}]) 


_.throttle(func, [wait=0], [options={}])

1. debounce
语法:
_.debounce(func, [wait=0], [options={}])
debounce函数通常称为防抖动函数,该函数会从上一次被调用后,延迟 wait 毫秒后调用 fn 方法

简单实现
function debounce(fn, wait, options) {   
    wait = wait || 0;   
    var timerId;    


    function debounced() {   
        if (timerId) {   
            clearTimeout(timerId);

            timerId = null;   
        }   
        timerId = setTimeout(function() {   
            fn();     
      }, wait);
   }
    return debounced;
 }
在上面的代码中,我们在debounce函数中定义了一个debounced()函数,内部定义了一个定时器,每当触发事件时,都会重置定时器,也就是说,当事件被执行时,并不会立刻执行fn,而是等待一定时间(wait)后才会执行。如果wait过后,函数没有再次被执行,就会处理最后一个fn。
注意:即使还有0.01秒就到指定时间,如果这时又执行了一次函数,那么之前的定时器就会被取消,需要重新等待到达指定时间。

2. Throttle
语法:
_.throttle(func, [wait=0], [options={}])
节流函数,在 wait 秒内最多执行 fn 一次的函数。

deboucne不同的是,throttle会有一个阀值,当到达阀值时,fn一定会执行。

简单实现

function throttle(fn, wait, options) {   
    wait = wait || 0;   
    var timerId, lastTime = 0;    
    
    function throttled() {   
        var currentTime = new Date();   
        if (currentTime >= lastTime + wait) {   
            fn();   
            lastTime = currentTime;   
        } else {   
            if (timerId) {   
                clearTimeout(timerId);   
                timerId = null;   
            }   
            timerId = setTimeout(function() {   
                fn()   
            }, wait);   
       }   
    }    
    return throttled;  
}
在上面的代码中,我们会记录每次函数被实际调用的时间,如果下次调用时,还没到达阀值,就会继续等待,直到到达阀值,就会调用最后一次函数。

完整实例
codepen.io/TGCode/pen/…

总结

  • debounce:将触发频繁的事件合并成一次执行。debounce适用于诸如input事件,当用户输入时需要响应ajax请求,多次input只响应一次回调方法
  • throttle: 设置一个阀值,在阀值内,将触发的事件合并成一次执行;且当到达阀值,必定执行一次事件。throttle适用于resize或者鼠标移动事件,防止浏览器频繁响应事件,严重拉低性能


参考文章
如有错误或疑问,欢迎在下方评论区留言!