节流和反跳功能之间的区别


250

任何人都可以用简单的词语解释一下为限制速率而对函数进行节流和反跳之间的区别。

在我看来,两者似乎都做同样的事情。我检查了这两个博客以了解:

http://remysharp.com/2010/07/21/throttling-function-calls

http://benalman.com/projects/jquery-throttle-debounce-plugin/


102
demo.nimius.net/debounce_throttle是一个很好的可视化文件
thriqon 2014年

4
@thriqon可视化效果比我的描述要好。
Donal 2014年

是的,那也帮助我理解了这个概念... ... +1为原作者;-)
thriqon 2014年

非常简单的示例帮助我理解了。jsfiddle.net/Voronar/sxjy25ew/1
Kirill A. Khalitov '17

1
可以在这里看到可视化效果以及codepen.io/chriscoyier/pen/vOZNQV
trungk18'7

Answers:


344

简单来说:

  • 节流将延迟执行功能。它将减少多次触发的事件的通知。
  • 防弹跳会将对函数的一系列顺序调用组合为对该函数的单个调用。它可以确保针对多次触发的事件做出一个通知。

您可以在这里直观地看到差异

如果您有一个被调用很多的函数-例如,当发生调整大小或鼠标移动事件时,可以多次调用它。如果您不希望这种行为,可以对其进行节流,以便定期调用该函数。防弹跳意味着在一系列事件的结尾(或开始)调用它。


9
我认为thriqon的可视化链接显示了它的工作原理。如果您有一个被调用很多的函数-例如,当发生调整大小或鼠标移动事件时,可以多次调用它。如果您不希望这样做,可以对其进行限制,以便定期调用该函数。防弹跳意味着将在一系列通话的结束(或开始)时调用它。
Donal 2014年

10
@AdamM。在这里查看可视化效果:demo.nimius.net/debounce_throttle
Donal

2
@AdamM。否。您可以通过在演示中移动鼠标并不时停止鼠标移动来形象地看到这一点。去抖杆会“嘀” 后,你停止了所有的鼠标移动,而油门杆将保持“滴答” ,而鼠标的移动,但在降低(节流)率。
John Weisz

26
我绝对放宽了可视化效果。谢谢!
Sammi

4
链接比千字更有价值
Finesse

148

就个人而言,我发现防抖节流阀更难理解。

由于这两个功能都可以帮助您推迟执行并降低执行速度。假设您反复调用油门/反跳返回的修饰函数...

  • 节气门:原始功能在指定的时间段内最多调用一次。
  • 防抖:在调用者在指定时间段后停止调用修饰的函数之后将调用原始函数。

我发现防抖的最后一部分对于理解其要实现的目标至关重要。我还发现_.debounce的旧版本实现有助于理解(由https://davidwalsh.name/function-debounce提供)。

// Returns a function, that, as long as it continues to be invoked, will not
// be triggered. The function will be called after it stops being called for
// N milliseconds. If `immediate` is passed, trigger the function on the
// leading edge, instead of the trailing.
_.debounce = function(func, wait, immediate) {
  var timeout;
  return function() {
    var context = this, args = arguments;
    var later = function() {
        timeout = null;
        if (!immediate) func.apply(context, args);
    };
    var callNow = immediate && !timeout;
    clearTimeout(timeout);
    timeout = setTimeout(later, wait);
    if (callNow) func.apply(context, args);
  };
};

一个牵强的比喻,但也许也有帮助。

您有一个名为Chatty的朋友,喜欢通过IM与您交谈。假设她说话时,她每5秒钟发送一条新消息,而您的IM应用程序图标则在上下跳动时,您可以...

  • 天真的方法:检查每条消息,只要它到达即可。当您的应用程序图标弹起时,请检查。这不是最有效的方法,但是您始终处于最新状态。
  • 节气门方法:每5分钟检查一次(如果有新检查)。当收到新消息时,如果您在最近5分钟内已检查过任何时间,请忽略它。使用这种方法可以节省时间,同时仍然可以循环使用。
  • 防抖方法:您知道Chatty,她将整个故事分解成小段,然后以一个接一个的消息发送。您需要等到Chatty结束整个故事:如果她停止发送消息5分钟,您就可以认为她已经完成了,现在检查所有内容。

17
直到我读了这本书,才明白这两个功能之间的区别。谢谢
Seamus Barrett

7
这个隐喻是我读过的关于油门和反跳的最伟大例子之一。谢谢。
Vignesh

96

差异性

+--------------+-------------------+-------------------+
|              |  Throttle 1 sec   |  Debounce 1 sec   |
+--------------+-------------------+-------------------+
| Delay        | no delay          | 1 sec delay       |
|              |                   |                   |
| Emits new if | last was emitted  | there is no input |
|              | before 1 sec      |  in last 1 sec    |
+--------------+-------------------+-------------------+

用例说明

  • 搜索栏-是否不想在用户每次按键时进行搜索?想要在用户停止键入1秒钟时进行搜索。使用debounce上的按键1秒。

  • 射击游戏-手枪每次射击之间需要1秒钟的时间,但是用户多次单击鼠标。throttle在鼠标单击时使用。

颠倒他们的角色

  • 在搜索栏上节流1秒钟 -如果用户键入abcdefghij中的每个字符,则该键为0.6 sec。然后,油门将在第一次a按下时触发。在接下来的1秒钟内它将忽略每次按下,即b在0.6秒钟处将被忽略。然后c在1.2秒将再次触发,这将重新设置时间。因此d将被忽略并被e触发。

  • 弹跳手枪1秒钟-当用户看到敌人时,他单击鼠标,但不会射击。他将在该秒内再次单击几次,但不会射击。他会查看它是否仍有子弹,这时(最后一次单击后1秒钟)手枪会自动射击。


37

节流会强制函数在一段时间内被调用的最大次数。如“每100毫秒最多执行一次此功能”中所述。

防反跳强制在不经过一定时间的情况下才再次调用该函数。就像“仅在经过100毫秒而不调用它时才执行此函数”中一样。

参考


20

油门(1秒):您好,我是机器人。只要您一直对我执行ping操作,我就会一直与您交谈,但每次恰好在1秒钟之后。如果您在不到一秒钟的时间内向我ping回复,我仍然会每隔1秒回复一次。换句话说,我只想按固定的间隔回复。

防反跳(1秒):嗨,我是那个^^机器人的表亲。只要您一直对我执行ping操作,我将保持沉默,因为自从您上次ping我以来,我只在经过1秒后才回复。我不知道是因为我的态度问题还是因为我不想打扰别人。换句话说,如果自上次调用以来一直在1秒钟之前要求我答复,那么您将永远不会得到答复。是的...继续前进!叫我粗鲁。


油门(10分钟):我是伐木机。定期间隔10分钟后,我会将系统日志发送到我们的后端服务器。

防抖动(10秒):嗨,我不是那台伐木机的堂兄。(在这个虚构的世界中,并非每个防抖器都与节流阀有关)。我在附近的一家餐馆当服务生。我应该告诉您,只要您继续向订单中添加商品,我就不会去厨房执行订单。上次修改订单后仅经过10秒钟,我将假定您已完成订单。只有这样,我才能在厨房执行您的订单。


酷演示:https//css-tricks.com/debouncing-throttling-explained-examples/

服务员类比的功劳:https : //codeburst.io/throttling-and-debouncing-in-javascript-b01cad5c8edf


1
最好的解释。
卡兰·沙尔玛

17

防弹跳使您可以管理函数可以接收的呼叫频率。它组合了在给定函数上发生的多个调用,因此将忽略在特定持续时间到期之前发生的重复调用。基本上防抖可确保针对可能发生多次的事件仅发送一个信号。

节流将函数接收的调用频率限制为固定的时间间隔。它用于确保目标函数的调用不超过指定的延迟。节流是重复事件发生率的降低。


17

这很简单。

它们执行完全相同的操作(速率限制),只是在调用节流阀时会定期触发您的包装函数,而反跳不会。反跳只是(尝试)在最后一次调用您的函数。

示例:如果您正在滚动,那么节流将在您滚动时(每X毫秒)缓慢调用您的函数。防弹跳将一直等到滚动完成之后再调用函数。


值得一提的是,在这些演示中,它们可能看起来并不“相同”,因为在发生最后一个事件后防抖总是会在X毫秒后触发,而油门的上一次调用可能会更早发生(并且在通常会触发防抖的情况下不需要再次调用)。这是无关紧要的,但是如果您看一下演示,则值得一提。
瑞安·泰勒

16

用外行的话来说:

反跳将防止功能运行,同时它仍然被频繁调用。防反跳功能仅确定不再被调用后才运行,这时它将恰好运行一次。防弹跳的实际示例:

  • 如果用户“停止键入”,则自动保存或验证文本字段的内容:在确定用户不再键入(不再按下键)之后,该操作仅执行一次。

  • 记录用户将鼠标放在何处:用户不再移动鼠标,因此可以记录(最后一个)位置。

如果调用函数最近运行,则节流将仅阻止该函数运行,而与调用频率无关。节流的实际示例:

  • v-sync的实现基于节流:仅在自上次屏幕绘制起经过16毫秒后才绘制屏幕。无论调用屏幕刷新功能多少次,它最多每16ms运行一次。

7

一个现实的类比,可以帮助我记住:

  • 去抖=对话。您等待对方说完话再回覆。
  • 油门=鼓点。您只能在简单的4/4鼓头上演奏音符。

防抖用例:

  • 打字。您想要在用户停止键入后执行某些操作。因此,在最后一次按键后等待1秒是有意义的。每次击键都会重新启动等待。
  • 动画。您要在用户停止将鼠标悬停在元素上之后将其收缩。由于光标在“热”和“冷”区域之间意外移动,因此不使用反跳可能会导致动画不稳定。

节流的用例:

  • 滚动。您希望对滚动做出反应,但要限制计算量,因此每100毫秒执行一次操作足以防止潜在的滞后。
  • 鼠标移动。与滚动相同,但用于鼠标移动。
  • API调用您想在某些UI事件上触发API调用,但想限制您进行的API调用次数,以免服务器过载。

4

throtle只是周围的包装去抖,这使得去抖调用通过function在一段时间内,如果去抖动延迟上的时间,这是更大然后在指定时间内的函数调用throtle



2

节流

节流强制执行一个函数超时的最大次数。如“每100毫秒最多执行一次此功能”中所述。假设在正常情况下,您将在10秒内调用此函数1,000次。如果将其每100毫秒调节一次,则该函数最多只能执行100次

(10s * 1,000) = 10,000ms
10,000ms / 100ms throttling = 100 maximum calls

防弹跳

防反跳强制在不经过一定时间的情况下才再次调用该函数。就像“仅在经过100毫秒而不调用它时才执行此函数”中一样。

也许一个函数被快速调用了1,000次,分散了3秒钟,然后停止调用。如果您在100毫秒处将其反跳,则一旦爆发结束,该功能将仅在3.1秒时触发一次。每次在猝发过程中调用该函数时,都会重置去抖计时器

来源:- 油门和反跳


2

假设我们有一个回调函数“ cb”在事件“ E”上被调用。让“ E”在1秒内被触发1000次,因此将有1000次调用“ cb”。就是1个通话/毫秒。为了优化,我们可以使用:

  • 节流:节流为(100ms)时,将在[第100毫秒,第200毫秒,第300毫秒,...第1000毫秒]调用“ cb”。即1个通话/ 100毫秒。在这里,将1000个呼叫“ cb”优化为10个呼叫。
  • 防抖动防抖动为(100ms),“ cb”仅在[1100th秒]被调用一次。这是在最后一次触发“ E”(在第1000毫秒)后100毫秒。此处将1000个呼叫“ cb”优化为1个呼叫。

1

据我了解,简单来说,节流-类似于调用setInterval(callback)一定次数,即在事件发生时随时间调用同一函数一定次数。或在事件发生后经过一定时间后调用函数。此链接可能有帮助-https : //css-tricks.com/the-difference-between-throttling-and-debouncing/

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.