JavaScript中的防抖动和限流
防抖动(debounce)和限流函数(throttle)
debounce 与 throttle 是开发中常用的高阶函数,作用都是为了防止函数被高频调用,换句话说就是,用来控制某个函数在一定时间内执行多少次。
Lodash 中的 debounce 函数
具体参数如下:
1 | interface debounceOptions { |
官方说明: 创建一个防抖动的函数,其主要目是, 延迟调用某个函数
创建一个
debounced
(防抖动)函数,该函数会从上一次被调用后,延迟 wait 毫秒后调用func
方法。debounced
(防抖动)函数提供一个cancel
方法取消延迟的函数调用以及flush
方法立即调用。 可以提供一个options
(选项)
对象决定如何调用func
方法,options.leading
与|或options.trailing
决定延迟前后如何触发(是 先调用后等待 还是
先等待后调用)。func
调用时会传入最后一次提供给debounced
(防抖动)函数 的参数。 后续调用的debounced
(防抖动)函数返回是最后一次func
调用的结果。
注意: 如果
leading
和trailing
选项为true
, 则func
允许trailing
方式调用的条件为: 在wait
期间多次调用防抖方法。
如果
wait
为0
并且leading
为false
,func
调用将被推迟到下一个点,类似setTimeout
为0
的超时。
示例
1 | // 避免窗口在变动时出现昂贵的计算开销。 |
动态演示
搬运及汉化自: https://css-tricks.com/debouncing-throttling-explained-examples/
See the Pen YzXpYVY by Bo.Jin (@BoJin) on CodePen.
具体应用
See the Pen Debouncing keystrokes Example by Bo.Jin (@BoJin) on CodePen.
Lodash 中的 Throttle 函数
1 | interface throttleOptions { |
创建一个节流函数,在
wait
秒内最多执行func
一次的函数。 该函数提供一个cancel
方法取消延迟的函数调用以及flush
方法立即调用。 可以提供一个options
对象决定如何调用func
方法,options.leading
与|或options.trailing
决定wait
前后如何触发。func
会传入最后一次传入的参数给这个函数。 随后调用的函数返回是最后一次func
调用的结果。
注意: 如果
leading
和trailing
都设定为true
则func
允许trailing
方式调用的条件为: 在wait
期间多次调用。
如果
wait
为0
并且leading
为false
,func
调用将被推迟到下一个点,类似setTimeout
为0
的超时。
示例
1 | // 避免在滚动时过分的更新定位 |
requestAnimationFrame (rAF)
无论是Debounce
还是throttle
,都提供了一种机制,就是requestAnimationFrame (rAF)
,他会产生一种类似于: _.throttle(fn, 16)
的效果,因为: $\frac{1000ms}{60Hz} = 16ms$,这是在 60Hz 的刷新率下的,如果改成了
47Hz,或者更高的刷新率,这个事件会相应的改变.
这样做有一个好处,就是处理关于动画的防抖动时,比如scroll, resize
等,不会超过刷新率,因为,这类防抖动,没有意义.
滚动示例
See the Pen Scroll comparison requestAnimationFrame vs throttle by Bo.Jin (@BoJin) on CodePen.
- 在上面的示例中, 可以看出,如果你的屏幕刷新率是
60Hz
, 你将无法感觉出使用rAF
和throttle-16ms
之间的区别.- 但是
throttle-50ms
你却可以看出明显的卡顿.- 如果你的屏幕分辨率是
20Hz
($\frac{1000ms}{50ms} = 20Hz$), 你将会感觉不到三者之间的区别,因为throttle-16ms
对于你来说没有意义,硬件性能达不到,而rAF
其实使用的就是50ms
.
参考资料
JavaScript中的防抖动和限流