该篇为翻译文章,原文地址为:The Difference Between Throttling and Debouncing – CSS Tricks
我之前被”节流”和”去抖”搞得很糊涂,后来有人帮我解决了这个问题。所以我把它写在这里也给大家解释一下。它们两个都是用来解决DOM事件的回调被不停调用而引起的性能问题的。但它们是有一定区别的。
节流
“节流”是限制一个一直在执行的函数的最大执行次数。比如让一个本来要一直执行的函数以最多100毫秒执行一次的频率来执行。
比如现在你遇到一个很奇怪的情况,一个函数不得不在10秒内执行1000次,但是实际上你是不需要它执行这么多次的。如果你把它限制在100毫秒执行一次,那么这个函数最终最多只会执行100次。
(10s * 1,000) = 10,000ms
10,000ms / 100ms 的节流 = 100 次的最大执行数
去抖
“去抖”则是等一段时间之后再去调用函数(并且函数此时没有被调用)。比如,在过了100毫秒后调用一个函数,并且该函数此时没有被调用。
在某些情况,一个函数可能会在不经意之间被调用1000次,这1000次的函数执行可能会花费3秒,3秒过后函数停止调用。如果你做一个100毫秒的去抖操作,函数将只会执行一次,在3.1秒的时候,也就是在你”不经意之间”结束的时候。
什么时候要”节流”和”去抖”
“节流”和”去抖”最重要的一个应用场景就是在某些DOM事件绑定上面,像是滚动和缩放窗口事件。比如一个元素绑定了滚动事件,当元素滚动了5000像素,你可能会发现你的事件函数执行了100多次。如果你的事件函数里有大量的代码(比如有一些大量的计算或者大量的DOM操作),那么则会产生一些性能上的问题。而这个时候如果你想在保证用户体验的同时做一些性能上的提升,那么就要看看”节流”或”去抖”的作用了。
一些常见的应用场景:
- 缩放浏览器窗口结束时
- 当输入停止时再发送Ajax请求
- 以最多50毫秒为时间单位来获取滚动的位置或者执行回调
- 在做拖拽操作的时候保证良好的性能
如何使用”节流”和”去抖”
这两个功能在Underscore和Lodash中都有集成。即使你的项目中不使用这两个库,你也可以把这些功能单独提取出来。
在滚动事件当中使用”节流”:
$("body").on('scroll', _.throttle(function() {
// Do expensive things
}, 100));
在缩放事件当中使用”去抖”:
$(window).on('resize', _.debounce(function() {
// Do expensive things
}, 100));
还有一个相对来说比较高级的做法,就是使用requestAnimationFrame
,使用了requestAnimationFrame
后,浏览器会在适当的时候执行函数。具体请看Paul Lewis的这篇文章.
最后通过下面这个Demo来体验一下它们之间的差别:
See the Pen The Difference Between Throttling, Debouncing, and Neither by Chris Coyier (@chriscoyier) on CodePen.