节流和去抖函数之间的区别

bha*_*a_w 198 javascript

任何人都可以给我一个简单的单词解释,说明为限速目的限制函数和去除函数之间的区别.

对我来说,两者似乎也做同样的事情.我查看了这两个博客,了解:

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

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

Don*_*nal 269

简单来说:

  • 限制将延迟执行功能.它将减少多次触发事件的通知.
  • Debouncing会将对函数的一系列顺序调用捆绑到对该函数的单个调用中.它确保为多次触发的事件发出一个通知.

您可以直观的看到差别在这里

如果你有一个被调用的函数 - 例如当调整大小或鼠标移动事件时,它可以被调用很多次.如果你不希望这种行为,你可以油门它,这样的函数被调用定期.去抖意味着它会在一堆事件的最后(或开始)被调用.

  • 我绝对不喜欢可视化.谢谢! (14认同)
  • 我认为thriqon的可视化链接显示了它如何运作良好.如果你有一个被调用的函数 - 例如当调整大小或鼠标移动事件时,它可以被调用很多次.如果你不想这样,你可以限制它,以便定期调用该函数.去抖意味着它会在一堆调用的最后(或开始)被调用. (7认同)
  • @AdamM.在这里查看可视化:http://demo.nimius.net/debounce_throttle/ (5认同)
  • 你开始于.. *“节流将延迟执行一个函数。”* 最后你说 *“通过去抖你正在延迟执行”* ...我以为我们正在谈论差异..? (2认同)
  • @AdamM.不可以.您可以通过在[demo](http://demo.nimius.net/debounce_throttle/)中移动鼠标来实现这一点,并且每隔一段时间停止鼠标移动.debounce-bar将"勾号"_ after_你停止所有鼠标移动,而油门栏将保持"滴答"_而鼠标移动,但是以减少(节流)的速率. (2认同)
  • 链接比千字更有价值 (2认同)

Dap*_* Li 125

就我个人而言,我觉得去抖更难理解而不是油门.

因为这两个函数都可以帮助您推迟并降低某些执行速度.假设您正在重复调用油门/去抖动返回的装饰函数...

  • 节流:每个指定时间段最多调用一次原始函数.
  • 去抖:在调用者在指定时间段后停止调用修饰函数后调用原始函数.

我发现去抖的最后一部分对于理解它试图实现的目标至关重要.我还发现_.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);
  };
};
Run Code Online (Sandbox Code Playgroud)

一个牵强附会的比喻,但也许也可能有所帮助.

你有一个名叫Chatty的朋友喜欢通过IM与你交谈.假设她说话时她每隔5秒发送一条新消息,而你的IM应用程序图标正在上下弹跳,你可以拿...

  • 天真的方法:只要到达就检查每条消息.当您的应用图标反弹时,请检查.这不是最有效的方式,但您始终是最新的.
  • 油门方法:每5分钟检查一次(当有新的时候).当新消息到达时,如果您在过去5分钟内随时检查过,请忽略它.使用这种方法可以节省您的时间,同时仍处于循环中.
  • 辩解方法:你知道Chatty,她将整个故事分解成碎片,然后一个接一个地发送它们.你等到Chatty完成整个故事:如果她停止发送消息5分钟,你会认为她已经完成,现在你检查所有.

  • 在我读这篇文章之前,我不明白这两个函数之间的区别.谢谢 (14认同)
  • 这个比喻是个好主意.很好地包装它 (5认同)
  • 这个比喻是我读过关于油门和去抖的最好的例子之一.谢谢. (5认同)

ami*_*309 73

用例说明:

搜索栏 -每次用户按键时都不想搜索?想要在用户停止输入1秒后进行搜索.debounce按键1秒后使用.

射击游戏 -手枪每次射击之间需要1秒的时间,但用户单击鼠标多次.用于throttle鼠标单击.

在逆转角色:

在搜索栏上节流1秒 - 如果用户在10秒内输入"长文字...",那么它应该调用搜索大约10次.当按下第一个键"L"时,将调用第一个搜索.

宣布手枪1秒 -当用户看到敌人时,他点击鼠标,但它不会射击.他将在那一秒再次点击几次,但它不会射击.他会看到它是否还有子弹,当时(最后一次点击后1秒)手枪会自动射击.

编辑:

差异

+--------------+-------------------+-------------------+
|              |  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    |
+--------------+-------------------+-------------------+
Run Code Online (Sandbox Code Playgroud)

  • 非常清楚的解释! (3认同)
  • @Rivenfall Throttle 和 Debounce 是为了减少噪音而设计的,所以它们的设计目的是为了失去一些人。他们有不同的流失人员策略。您正在寻找的是延迟运算符[https://rxjs.dev/api/operators/delay]。这只会延迟他们的反应。延迟守卫将是普通守卫,只是他处理声音需要 5 秒。因此将允许所有但在 5 秒延迟后。 (2认同)

Ans*_*hul 32

限制强制执行可以随时间调用函数的最大次数.如"每100毫秒最多执行一次此功能".

Debouncing强制执行一个函数不会被调用,直到一定时间过去而没有被调用.如"只有在没有被调用的情况下经过100毫秒才执行此函数".

REF


Gil*_*ain 25

一张图片胜过千言万语

风门 风门

去抖动 去抖动

请注意,在事件流停止之前, Debounce不会触发。但是,Throttle将在每个时间间隔触发一个事件。

(感谢css-tricks

  • 我无法想象如果原始事件在油门和去抖图像上都匹配的话,还值得多少文字…… (7认同)

Gib*_*boK 16

Debouncing允许您管理函数可以接收的调用频率.它结合了在给定函数上发生的多个调用,以便忽略在特定持续时间到期之前发生的重复调用.基本上,去抖动可确保为可能多次发生的事件发送一个信号.

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


cho*_*hoc 15

油门(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

  • 最好的解释。 (8认同)

Guy*_*Guy 15

一个个人帮助我记住的现实生活类比:

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

去抖动的用例:

  • 打字。你想在用户停止输入后做一些事情。所以在最后一次击键后等待 1 秒是有道理的。每次击键都会重新开始等待。
  • 动画片。你想在用户停止悬停在一个元素上后缩小它。由于光标在“热”和“冷”区域之间无意移动,不使用去抖动可能会导致动画不稳定。

油门的用例:

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


Joh*_*isz 14

通俗地说:

反跳将防止功能运行,同时它仍然被频繁调用.去抖动函数只有确定不再被调用之后才会运行,此时它将只运行一次.去抖的实际例子:

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

  • 记录用户放置鼠标的位置:用户不再移动鼠标,因此可以记录(最后)位置.

无论呼叫频率如何,限制都会阻止函数在最近运行时运行.限制的实际例子:

  • v-sync的实现基于限制:仅在自上次屏幕绘制后经过16ms时才会绘制屏幕.无论调用屏幕刷新功能多少次,它每16ms最多只能运行一次.


Rya*_*lor 13

这很简单。

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

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


win*_*mao 12

将去抖动和油门放在一起可能会非常令人困惑,因为它们都共享一个名为 的参数delay

在此输入图像描述

去抖。就是delay等到不再有调用时再调用它。非常像关电梯门:门必须等到没有人试图进入才能关闭。

油门。是以delay某个频率等待,然后调用最后一个。很像手枪的射击,枪的射击速度不能超过一定的速度。


让我们看一下实现细节。

function debounce(fn, delay) {
  let handle = null
  
  return function () {
    if (handle) {
      handle = clearTimeout(handle)
    }
    
    handle = setTimeout(() => {
      fn(...arguments)
    }, delay)
  }
}
Run Code Online (Sandbox Code Playgroud)

Debounce,不断中断超时,直到不再有中断,然后触发fn

function throttle(fn, delay) {
  let handle = null
  let prevArgs = undefined
  
  return function() {
    prevArgs = arguments
    if (!handle) {
      fn(...prevArgs)
      prevArgs = null
      handle = setInterval(() => {
        if (!prevArgs) {
          handle = clearInterval(handle)
        } else {
          fn(...prevArgs)
          prevArgs = null
        }
      }, delay)
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

Throttle,存储最后一次调用参数,并设置触发时间间隔,直到不再触发过去的事件。

相似之处。它们都有延迟时间,延迟期间不会发生火灾,尤其是只有一处火灾时。两者都不会汇总过去的事件,因此事件的数量可能与实际火灾的数量不同。

不同之处。在重复事件的去抖情况下,可以延长延迟。而节气门情况下的延迟是固定的。因此,一般来说,油门引起的火灾多于反跳引起的火灾。

容易记住。去抖动将捆绑呼叫合并为一个。Throttle 将捆绑调用保持在一定频率内。

更新于 23 年 1 月 20 日

Throttle 可能不需要,这是我最近编写的一个新版本,它也setInterval可以解决这个问题。this

function throttle(fn, delay) {
  let canFire = true
  let queue = []

  function pop() {
    if (queue.length < 1) return 

    const [that, args] = queue.pop()
    fn.apply(that, args)
    canFire = false
    setTimeout(() => {
      canFire = true
      pop()
    }, delay)
  }
  
  function push() {
    queue.push([this, arguments])
    if (canFire) pop()
  } 

  push.cancel = () => {
    queue = []
  }

  return push
}
Run Code Online (Sandbox Code Playgroud)

更新于 11-09-23

我开始相信油门是除抖之外的附加组件。阅读此https://windmaomao.medium.com/throttle-is-a-debounce-add-on-80d4a6027ad4

function throttle(fn, delay) {
  let h
  let queue = []

  function pop() {
    if (queue.length < 1) return 

    if (!h) {
      const [that, args] = queue.pop()
      fn.apply(that, args) 
      
      h = setTimeout(() => {
        h = null
        pop()
      }, delay)      
    }      
  }
  
  return function push() {
    queue.push([this, arguments])
    pop()
  } 
}
Run Code Online (Sandbox Code Playgroud)


baj*_*ran 7

节流

限制强制执行函数可以超时调用的最大次数。如“最多每 100 毫秒执行一次此函数”。假设在正常情况下,您会在 10 秒内调用此函数 1,000 次。如果您将其限制为每 100 毫秒仅一次,则该函数最多只会执行 100 次

(10s * 1,000) = 10,000ms
10,000ms / 100ms throttling = 100 maximum calls
Run Code Online (Sandbox Code Playgroud)

去抖动

去抖动强制一个函数在一段时间内不被调用之前不会被再次调用。如“仅当 100 毫秒过去了而没有被调用时才执行此函数”。

也许一个函数在快速爆发中被调用 1,000 次,分散超过 3 秒,然后停止被调用。如果您在 100 毫秒时对其进行了去抖动,则该函数将仅在 3.1 秒时触发一次,一旦爆发结束。每次在突发期间调用该函数时,它都会重置去抖动计时器

来源:-节流和去抖动


Ole*_*yba 5

throtle只是debounce 的包装器,如果debounce延迟函数调用function的时间段大于throttle中指定的时间段,则 debounce 会在一段时间内传递调用。


Nat*_*Geo 5

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

  • 节流:节流为 (100ms) 时,将在 [第 100 毫秒、第 200 毫秒、第 300 毫秒、...第 1000 毫秒] 调用“cb”。即 1 次调用/100 毫秒。这里对“cb”的 1000 次调用优化为 10 次调用。
  • 去抖动:当去抖动为 (100ms) 时,“cb”将仅在 [第 1100 秒] 被调用一次。这是在[第 1000 毫秒]最后一次触发“E”之后的 100 毫秒。这里对“cb”的 1000 次调用优化为 1 次调用。