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

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

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

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


当前回答

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

其他回答

debound使函数只能在最后一次调用后的一段时间后执行

function debounce(func,wait){
  let timeout
  return(...arg) =>{
    clearTimeout(timeout);
    timeout= setTimeout(()=>func.apply(this,arg),wait)
  }
}


function SayHello(){
  console.log("Jesus is saying hello!!")
}


let x = debounce(SayHello,3000)
x()

节流模式限制了在一段时间内可以调用给定事件处理程序的最大次数。它允许以指定的时间间隔周期性地调用处理程序,忽略该等待期结束之前发生的每个调用。

function throttle(callback, interval) {
  let enableCall = true;

  return (...args)=> {
    if (!enableCall) return;

    enableCall = false;
    callback.apply(this, args);
    setTimeout(() => enableCall = true, interval);
  }
}


function helloFromThrottle(){
  console.log("Jesus is saying hi!!!")
}

const foo = throttle(helloFromThrottle,5000)
foo()

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

谈话结束。你等对方说完再回答。 鼓形钻头。你只在简单的4/4鼓位上演奏音符。

debounce的用例:

打字。你想在用户停止输入后做一些事情。所以在最后一次击键后等待1秒是有意义的。每次击键重新启动等待。 动画。当用户停止将鼠标悬停在某个元素上时,需要将其收缩。不使用debounce可能会导致不稳定的动画,因为光标会无意中在“热”和“冷”区域之间移动。

节流的用例:

滚动。你想要对滚动做出反应,但限制所做的计算量,所以每100毫秒做一些事情就足以防止潜在的延迟。 鼠标移动。与滚动相同,但用于鼠标移动。 API调用你想在某些UI事件上触发API调用,但想限制API调用的数量,以免使服务器过载。

一幅图胜过千言万语

节气门

防反跳

注意Debounce直到事件流停止才会触发。但是,Throttle会在每个间隔时间内触发一个事件。

(感谢css-tricks)

差异

+--------------+-------------------+-------------------+
|              |  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 SEC按下键。 射击游戏-手枪每次射击之间需要1秒的时间,但用户点击鼠标多次。在鼠标点击时使用油门。

角色互换:

Throttling 1 sec on search bar- If users types abcdefghij with every character in 0.6 sec. Then throttle will trigger at first a press. It will will ignore every press for next 1 sec i.e. bat .6 sec will be ignored. Then c at 1.2 sec will again trigger, which resets the time again. So d will be ignored and e will get triggered. Debouncing pistol for 1 sec- When user sees an enemy, he clicks mouse, but it will not shoot. He will click again several times in that sec but it will not shoot. He will see if it still has bullets, at that time (1 sec after last click) pistol will fire automatically.

进一步解释投入产出与现实生活的比较

酒吧外面有几个警卫。警卫允许说“我去”的人进入酒吧。这是正常的情况。任何说“我去”的人都可以进入酒吧。

现在有一个Throttle Guard(节流5秒)。他喜欢最先回应的人。谁先说“我要去”,他就让那个人去。然后他会在5秒内拒绝每个人。在这之后,无论谁先说,他都会被允许,其他人会被拒绝5秒。

还有另一个弹跳守卫(弹跳5秒)。他喜欢能让他精神休息5秒钟的人。所以如果有人说“我去”,警卫会等5秒钟。如果5秒钟内没有其他人打扰他,他会允许第一个人打扰他。如果有人在这5秒内说“我要去”,他会拒绝第一个。他又开始了等待第二个人的5秒,看第二个人是否能让他得到精神上的休息。

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

节流:节流(100ms),“cb”将 在第100毫秒,第200毫秒,第300毫秒,…1000 ms)。也就是1次呼叫/100毫秒。这里对“cb”的1000次调用优化为10次调用。 debounning:当debounning为(100ms)时,“cb”只会在[1100秒]被调用一次。这是发生在第1000毫秒的最后一次触发“E”后的100毫秒。这里对“cb”的1000次调用优化为1次调用。