去抖函数和节流函数之间的差异
本本文翻译自The Difference Between Throttling and Debouncing
之前一些天我有一些糊涂直到有人解决了我的问题。所以我将它整理好作为博客文章发布出来。去抖和节流都是一种用来限制javascript代码执行次数的方法,基于DOM事件,来解决性能问题。但是你大概能猜到,它们之间有一些差异。
节流会强制规定在单位时间内一个函数调用的最大次数。例如每过100毫秒至少执行一次这个函数。
也就是说在普通情况下10秒钟你可以调用这个函数1000次。如果你对这个函数节流到每100毫秒才能调用一次,那么10秒就只能调用100次
(10秒 * 1,000) = 10,000毫秒
10,000毫秒 / 100毫秒 节流后等待时间 = 100 最大调用次数
去抖会强制一个函数不被重复调用直到等待指定时间已经过去并且等待期间没有被调用。例如在距离上次调用之后100毫秒后才能调用下一次函数。
也许一个函数在被快速触发的情况下会被调用1000次,时间间隔是3秒钟,然后停止调用。如果你让这个函数去抖100毫秒,那么一旦频繁触发停止了,这个函数在3.1秒的时候只会触发1次。每一次频繁触发的时候去抖的定时器都会被重新设置。
关键点是什么?
这两个概念的一个主要使用场景就是某些DOM事件,像滚动事件scroll和改变窗口大小事件resize。举个例子, 如果你绑定了一个滚动事件处理器到一个元素上,然后滚动那个元素的滚动条到5000像素处,你可能会看到事件处理函数被触发了超过100次。如果这个事件处理器做了一大堆处理(像很重的运算和其他DOM操作),那么可能页面会发生性能问题。如果你能避免频繁触发事件处理函数,那么对于页面效率来说是值得的。
常见例子:
- 等待用户停止改变窗口大小后再触发事件处理器
- 直到用户停止输入后再触发ajax请求
- 测量滚动到的页面的位置然后每50毫秒就响应一次
- 当你在应用中拖拽一个元素的时候确保页面运行良好,不会出现性能问题
怎样去做?
这两个函数在underscore和lodash库中都已经定义好了。如果你不想使用整个underscore和lodash库,你可以将这两个方法单独提取引入。
节流滚动例子:
$("body").on('scroll', _.throttle(function() { // Do expensive things }, 100));
去抖resize:
$(window).on('resize', _.debounce(function() { // Do expensive things }, 100));
例子
简单例子可以查看节流和去抖直接的区别
The Difference Between Throttling, Debouncing, and Neither[CodePen]