谁能给我一个简单的解释,关于节流和debounging函数之间的区别,以限制速率的目的。

在我看来,两者的作用是一样的。我查看了这两个博客来找出答案:

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

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


当前回答

这篇文章解释得很好,也有图形。

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

从文章中(并进行了一些澄清):

这(节流)和deboundation之间的主要区别在于节流保证了函数的定期执行,至少每X毫秒执行一次。

通常debounce在指定时间结束时调用函数,而throttle在第一次调用节流函数时调用。有时debounce可以采取额外的配置,将此更改为在开始时执行调用。当使用特定的配置调用时,debounce的一些实现实际上可以做油门所做的事情(参见Lodash源代码)。

其他回答

lodash库建议以下文章https://css-tricks.com/debouncing-throttling-explained-examples/详细解释Debounce和Throttle之间的区别及其起源

Throtle只是debounce的包装器,它使debounce在一段时间内调用传递的函数,如果debounce在一段时间内延迟函数调用,该时间大于Throtle中指定的时间。

将debounce和throttle放在一起可能会非常令人困惑,因为它们都共享一个称为延迟的参数。

防反跳。延迟是等到不再有调用时,再调用它。就像关闭电梯门一样:门必须等到没有人试图进入时才能关闭。

节流。延迟是以一定的频率等待,然后调用最后一个。很像手枪射击,枪只是不能超过一定的射速。


让我们看一看实现的细节。

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

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)
    }
  }
}

Throttle,存储最后一个调用参数,并设置一个间隔来触发,直到没有过去的调用。

相似之处。它们都有延迟时间,并且在延迟期间不会发生火灾,特别是当只有一场火灾时。两者都不聚合过去的事件,因此事件的数量可能与实际的火灾不同。

的区别。在有重复事件的弹跳情况下,延迟可以延长。而在节流阀情况下的延迟是固定的。所以一般来说,油门产生的火焰比反弹产生的火焰要多。

很容易记住。将组捆绑为一个。节流保持捆绑调用在一定的频率。

更新1-20-23

Throttle可能不需要setInterval,这是我最近写的一个新版本,它也照顾到了这个问题。

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
}

油门(1秒):你好,我是机器人。只要你一直打我,我就会继续和你说话,但每次一秒后。如果你在一秒之前ping我的回复,我仍然会在1秒的间隔内回复你。换句话说,我就是喜欢隔一定的时间间隔回复。

弹跳(1秒):嗨,我是那个^^机器人的表弟。只要你一直ping我,我就会保持沉默,因为我喜欢在你最后一次ping我一秒钟后才回复。我不知道,是因为我的态度有问题还是因为我不喜欢打断别人。换句话说,如果您在上次调用后的1秒内一直向我请求回复,您将永远不会得到回复。是的是的…去吧!说我粗鲁就好。


节流阀(10分钟):我是一台伐木机。我将系统日志发送到我们的后端服务器,每隔10分钟。

反弹(10秒):嗨,我不是那台伐木机的表亲。(在这个想象的世界中,并不是每个脱锁器都与节流器有关)。我在附近一家餐馆当服务员。我应该让你知道,只要你一直在你的订单中添加东西,我就不会去厨房执行你的订单。只有在您上次修改订单后10秒后,我才会认为您已经完成了订单。到那时我才会去厨房执行您点的菜。


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

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

这里真正重要的是,用最简单的话说:如果你有一些连续重复一段时间的操作(如鼠标移动,或页面大小调整事件),你需要运行一些函数来响应,但你不想对每个操作都做出反应(因为这可能会损害性能),你有两个选择:

debounce - you skip all incoming actions, except the last one (the 'last one' is defined by the 'wait' time period you set for debounce function, for example, 2s - it will consider that actions flood stopped, if no actions were taken for 2s, and then it will react. This strategy is reasonable if you don't care about regular updates, you just need to react at least once. throttle - if you want to react 'on schedule', to make regular updates even if actions flood is endless, you make your function run at regular intervals (no more often, then the specified time interval), for example 2s throttling will mean that your response will be executed an once if action is taken, but no less then 2s after that. So with continuous actions flood your response will be run on 0s, 2s, 4s, 6s, 8s...