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

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

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

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


当前回答

节流

节流强制一个函数可以被调用的最大次数 加班。就像“每100次执行一次这个函数 毫秒。”假设在正常情况下你会这样做 在10秒内运行1000次。如果你把它控制在一次 每100毫秒,它最多只执行该函数100次 次

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

消除抖动

撤销强制函数不再被调用,直到 一段时间过去了,它还没有被调用。就像在 “只有在100毫秒之后才执行这个函数 被称为”。

也许一个函数在短时间内被调用1000次,分散在3秒内,然后停止被调用。如果您在100毫秒时将其解除,则该函数只会在爆发结束后的3.1秒内触发一次。每次在爆发期间调用该函数时,它都会重置反弹计时器

来源:-油门和反弹

其他回答

将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将阻止一个函数在仍然被频繁调用时运行。debound函数只在确定不再被调用后才会运行,此时它只会运行一次。脱绳的实际例子:

如果用户“停止输入”,自动保存或验证文本字段的内容:该操作将只执行一次,在确定用户不再输入(不再按键)之后。 记录用户休息鼠标的位置:用户不再移动鼠标,因此可以记录(最后)位置。

节流只会阻止最近运行过的函数运行,不管调用频率如何。节流的实际例子:

v-sync的实现是基于节流的:从上一次绘制屏幕到现在已经过去了16ms,屏幕才会被绘制。无论调用多少次屏幕刷新功能,它最多只能每16毫秒运行一次。

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

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

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

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

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

节流阀的简单概念是在表单中频繁点击提交按钮,我们需要使用节流阀。因此提交功能可以防止频繁点击。它将相同的请求保存到函数中。

关于debounce,编写了一个简单的带有输入文本标签的代码,用于从服务器上搜索一些数据。Oninput使用debounce删除之前的请求,并将最后输入的单词传递给服务器

const throttle = (callback, time = 0) => {
    let throttle_req, count = 0;
     return async function () {
         var context = this, args = arguments;  
         if(throttle_req) return;  
         throttle_req = true; 
         if(time > 0)
         {
             callback.apply(context, args); 
             setTimeout(() => {
              throttle_req = false; 
             }, time || 200) 
         }
         else
         {
           let response = await callback.apply(context, args); 
            throttle_req = false; 
           return response;
         } 
     }
  }
const debounce = (callback, time = 0) => {
    let debounce_req;
    return function () {
        var context = this, args = arguments;
        clearTimeout(debounce_req) 
        debounce_req = setTimeout(() => {
             debounce_req = null;
             callback.apply(context, args);
        }, time || 200) 
    }
}

我们如何调用:只是用节流或debounce包装你的函数来检查差异

节流阀:同一按钮点击超过1次

var throttleFunct = throttle(function(num) {
  console.log(num, "hello throttle")
}, 2000);
throttleFunct(300) //it execute. because its the first call
throttleFunct(400) //it won't execute

节流异步没有时间

var getDataAsync =  throttle(function(id, name) {
    return new Promise((resolve) => {  
      setTimeout(() => {
            resolve({name: name, id: id})
      }, 2000)
     }) 
});
async function test() {
let response = await getDataAsync(120, 'Sherley').then(resp => resp)  
console.log(response, "respond") //it execute. because its the first call
response = await getDataAsync(120, 'James').then(resp => resp)  
console.log(response, "respond2")//it executes 2 after first request
response = await getDataAsync(120, 'Jonathan').then(resp => resp)  
console.log(response, "respond3")//it executes 3 after second request
    }
    test()

例如:搜索框自动完成

var debounceFunct = debounce(function(num) {
  console.log(num+1)
}, 2000);
debounceFunct(300) //it won't execute and it cancelled
debounceFunct(400) // it executes and it replaced with the previous call. because this is the latest event fire

简单来说:

节流将延迟执行函数。它将减少多次触发事件的通知。 deboundation将一系列对函数的连续调用合并为对该函数的单个调用。它确保为多次触发的事件发出一个通知。

你可以直观地看到其中的区别

如果你有一个函数被调用了很多次——例如当一个调整大小或鼠标移动事件发生时,它可以被调用很多次。如果您不想要这种行为,您可以Throttle它,以便定期调用该函数。deboning将意味着它在一系列事件的结束(或开始)时被调用。