对我来说,这两个似乎是在做同样的事情。我查了这两个博客,但我仍然难以理解。
http://remysharp.com/2010/07/21/throttling-function-calls
http://benalman.com/projects/jquery-throttle-debounce-plugin/
http://remysharp.com/2010/07/21/throttling-function-calls
http://benalman.com/projects/jquery-throttle-debounce-plugin/
个人认为 debounce 比 throttle 更难理解。
因为这两个函数都有助于推迟和降低某些代码的执行频率。假设您正在反复调用由 throttle/debounce 返回的修饰函数......
我发现 debounce 的最后部分很重要,可以理解它试图实现的目标。我还发现 _.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 的朋友,她喜欢通过即时通讯和你聊天。假设每当她说话时,她会每隔5秒钟发送一条新的消息。当你的即时通讯应用程序图标上下跳动时,你可以采取以下三种方法:
区别
+--------------+-------------------+-------------------+
| | 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秒后进行搜索。 在按键时使用1秒的防抖
。
射击游戏-手枪每次射击需要1秒钟的时间,但用户会多次点击鼠标。 在鼠标点击上使用节流
。
反转它们的角色:
对搜索栏进行1秒的节流- 如果用户在每个字符中0.6秒
内输入abcdefghij
。 那么,第一个按下时将触发节流
。 接下来的1秒钟内,即0.6秒,将忽略每次按键,即 0.6秒 将被忽略。 然后,在1.2秒时, 将再次被触发,这将再次重置时间。 所以将被忽略而将被触发。
对手枪进行1秒的防抖- 当用户看到敌人时,他点击鼠标,但不会射击。 在那一秒钟内,他将再次多次单击鼠标,但它仍不会射击。 它将查看是否还有子弹,此时(最后一次单击后1秒钟)手枪将自动开火。
进一步解释输入输出与现实生活的比较
有一些保安在酒吧外面。 保安允许说“我会去”的人进入酒吧。 这是正常情况。 任何说“我会去”的人都可以进入酒吧。
现在有一个节流守卫(节流5秒
)。 他喜欢先回应的人。 第一个说出“我会去”的人,他就允许那个人进入。 然后,在5秒内,他拒绝每个人。 之后,再次有人首先说这句话,他就允许了,并且其他人将被拒绝5秒。
还有另一个防抖守卫(防抖5秒
)。 他喜欢带给他5秒钟的心理休息的人。 所以如果有任何人说“我会去”,守卫会等待5秒钟。 如果在这5秒内没有其他人打扰他,他就允许第一个人进入。 如果另一个人在这5秒内说“我会去”,他将拒绝第一个人。 他会重新开始5秒的等待,以查看第二个人是否能为他带来心理休息。
节流(1秒): 你好,我是一个机器人。只要你继续发送请求给我,我就会继续回复你,但是每次回复的时间间隔恰好为1秒。如果在一秒内再次发送请求给我,我仍会在恰好1秒的时间间隔后回复你。换句话说,我喜欢以精确的间隔回复。
去抖动(1秒): 嗨,我是那个 ^^ 机器人的表兄弟。只要你不断地发送请求给我,我将保持沉默,因为我喜欢在上一次收到请求后过了1秒才回复。我不知道这是因为我有态度问题还是我不想打断别人。换句话说,如果你在上次调用后的1秒内继续请求回复,你将永远得不到回复。是啊,呵呵...你可以称呼我为粗鲁。
节流(10分钟): 我是一个日志记录机器。我会在每隔10分钟定期向我们的后端服务器发送系统日志。
去抖(10秒):嗨,我不是那个日志记录机器的表兄弟。(在这个虚构的世界中,并非每个去抖器都与节流器有关系)。我在附近的餐馆做服务员。我应该告诉你,只要你继续添加订单,我就不会去厨房执行你的订单。只有在你最后修改订单后经过10秒钟,我才会认为你已经完成订单。然后我才会去厨房执行你的订单。
炫酷演示:https://css-tricks.com/debouncing-throttling-explained-examples/
服务员比喻来源:https://codeburst.io/throttling-and-debouncing-in-javascript-b01cad5c8edf
节流(Throttling)强制规定了函数在一段时间内最多被调用的次数。例如,“每100毫秒最多只执行一次此函数”。
防抖(Debouncing)强制规定了函数必须在一定的时间内不被再次调用才能执行。例如,“只有在100毫秒内没有调用时才执行此函数”。
当调用节流时,它会定期触发您的函数(例如,每20毫秒一次)- 并在最后一次触发时触发。
防抖只在最后触发(例如,最后一个事件之后的20毫秒)。
因此,只要事件继续快速触发(例如,间隔小于20毫秒),防抖将保持沉默,而节流将每20毫秒触发一次。两者都会在最后触发,区别只在于节流还会在设定的间隔内触发。
示例:如果您正在滚动,节流将在滚动时缓慢调用您的函数(每X毫秒一次)。防抖将等待您完成滚动后才调用您的函数(可能只调用一次)。
用通俗易懂的语言来说:
防抖可以防止一个函数在频繁调用时重复运行。只有在确定该函数不再被调用后,它才会运行一次。防抖的实际例子包括:
如果用户停止输入文本,则自动保存或验证文本框内容:操作只会在确定用户不再输入(不再按键)后运行一次。
记录用户鼠标静止位置:用户不再移动鼠标,因此可以记录(最后的)鼠标位置。
节流将简单地防止函数在最近已运行过时再次运行,而不考虑调用频率。节流的实际例子包括:
一个我个人觉得很有帮助的现实生活比喻:
debounce 的使用场景:
throttle 的使用场景:
去抖动(Debouncing)允许您管理函数可以接收的调用频率。它组合了在给定函数上发生的多个调用,以便在特定时间段到期之前发生重复调用时被忽略。基本上,去抖动确保为可能多次发生的事件只发送一个信号。
节流(Throttling)限制了函数接收调用的频率至固定的时间间隔内。它用于确保目标函数不会比指定延迟更频繁地调用。节流是重复事件速率的减少。