zqqcee

Comes in a big package "📦"

0%

浅析Debounce与Throttle的区别

这两天在学习前端知识,在Vue的官方教程中看到了这两个概念,查阅相关资料后,做以下整理。

概述

DebounceThrottle是两个非常相似,但不相同的方法,它们都用来控制我们允许一个函数随时间执行的次数,用官方一点的说法就是:防止抖动。但是它们又有不同,以鼠标点击事件绑定的函数clickFunc()为例:假设用户在10秒内不间断点击50下鼠标

  • debounce(clickFunc(),delay)是将这50次鼠标在用户停止点击鼠标点击动作的delay秒后,才响应一次。
  • throttle(clickFunc(),delay)是在delay秒的时间间隔内。无论用户点击多少次,只响应一次。

讲到这里可能还不是很清楚,但没关系,接下来这个例子可以帮助你更好地理解它们的区别

再举一个例子:比如我们现在有一个函数需要响应用户的滚动交互。我们都知道,用户可以通过鼠标滚轮和拖动侧边的长条形bar进行滚动交互。

  • 如果滚动一个单位,我们就需要操作一次DOM元素。那么用户如果每秒滚动100个单位,是根本无法全部响应的,还会造成浏览器卡死。所以我们可以使用debounce(),让用户停止滚动后再响应。
  • 经常刷微博逛知乎的朋友应该都知道,我们即将滑动到底部的时候,前端会请求更多内容以方便我们查阅。这是怎么做到的呢?其实就是用了throttle(func(),delay)函数,其中func()是一个检测是否快到底部的函数,delay用来控制多长时间间隔内,浏览器响应一次。用户执行滚动事件的时候,就会判定是否靠近底部,如果靠近底部就发一个AJAX请求新一批内容。这也避免了这个函数一直监听,用户靠近底部的每一次滑动都去请求服务器,然后给服务器带来很多不必要的负担。

这两个函数在我们将某个函数绑定到操作DOM元素的事件上非常有用,为什么这么说呢?
这两个函数的出现,其实相当于我们在事件响应和函数执行间添加了一个控制层。显然这是非常有必要的,因为我们无法控制用户如何进行交互,但是我们可以控制前端如何响应这些用户的交互。

Debounce

可以理解成把一些连续的操作视为一组序列,最终浏览器只把这组序列视为一个事件进行响应。
如图,第一排为用户的时间,第二排为浏览器的响应
在这里插入图片描述
“归为一组响应”的理解:
在这里插入图片描述
为了方便理解debounce(),在这里举个例子:想像现在有一个电梯,如果检测到当前有人进来就延迟5s关门。现在第一个人走进电梯,过了3s,还差2s关门的时候,电梯又走进来了一个人。那么在第二个人走进来之后,电梯会重设计时器,重新计时5s再关门。同理,第三个人如果在这5s间隔内走进电梯,电梯又会重新计时。

瞬时响应or延迟响应

其实这很容易带来一个问题,那就是现在我们介绍的debounce()函数事实上是延迟响应的。也就是说当我们进行连续的交互后,要过一定时间才会响应我们的交互事件。那如果我们要让它马上就响应一次我们的交互呢?debounce()给我们提供了参数让我们来控制是瞬时响应还是延迟响应。
下面放上一张瞬时响应的示意图,可以看到,虽然还是把这些交互归为了一组,只响应一次。但响应的是用户一开始触发交互事件
在这里插入图片描述

举例与注意事项

debounce()可以用于用户输入,用户调整浏览器窗口大小等。

比如在用户注册界面,等用户停止输入邮箱后,判断用户输入的内容是否符合邮箱校验规则。

在使用时,我们要注意一个地方。就是debounce()不能被多次调用,下面给出了一种正确用法与一种错误用法,请读者自行体会。

  • WRONG
    $(window).on('scroll', function() {
    _.debounce(doSomething, 300);
    });
  • RIGHT
    $(window).on('scroll', _.debounce(doSomething, 200));

    Throttle

    定义

    这前面简单介绍过了,这里就不过多赘述。它的定义是:
    不允许某个函数在{delay}长度的时间间隔内执行超过一次

用法举例

它的用法与debounce()相似,以lodash.js为例:

_.throttle(dosomething, 16)

主要用在检测用户界面是否已经靠近底部了,如果靠近底部就需要请求新的内容供用户查阅。

参考文章

Debouncing and Throttling Explained Through Examples