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

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

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

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


当前回答

我个人认为反弹比油门更难理解。

因为这两个函数都可以帮助您延迟和降低某些执行的速度。假设您正在调用由throttle/debounce反复返回的装饰函数…

节流:在指定的时间段内,原函数最多被调用一次。 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的朋友,他喜欢通过IM和你聊天。假设当她说话时,她每5秒发送一条新消息,而你的即时通讯应用程序图标上下跳动,你可以…

Naive approach: check every message as long as it arrives. When your app icon bounces, check. It's not the most effective way, but you are always up-to-date. Throttle approach: you check once every 5 minutes (when there are new ones). When new message arrives, if you have checked anytime in the last 5 minutes, ignore it. You save your time with this approach, while still in the loop. Debounce approach: you know Chatty, she breaks down a whole story into pieces, sends them in one message after another. You wait until Chatty finishes the whole story: if she stops sending messages for 5 minutes, you would assume she has finished, now you check all.

其他回答

简单来说:

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

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

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

debound允许您管理函数可以接收的调用频率。它将发生在给定函数上的多个调用组合在一起,以便忽略在特定时间持续时间到期之前发生的重复调用。从根本上说,deboundation确保了一个可能发生多次的事件只发送了一个信号。

节流将函数接收的调用频率限制在固定的时间间隔内。它用于确保目标函数的调用频率不会超过指定的延迟。节流是降低重复事件的速率。

我个人认为反弹比油门更难理解。

因为这两个函数都可以帮助您延迟和降低某些执行的速度。假设您正在调用由throttle/debounce反复返回的装饰函数…

节流:在指定的时间段内,原函数最多被调用一次。 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的朋友,他喜欢通过IM和你聊天。假设当她说话时,她每5秒发送一条新消息,而你的即时通讯应用程序图标上下跳动,你可以…

Naive approach: check every message as long as it arrives. When your app icon bounces, check. It's not the most effective way, but you are always up-to-date. Throttle approach: you check once every 5 minutes (when there are new ones). When new message arrives, if you have checked anytime in the last 5 minutes, ignore it. You save your time with this approach, while still in the loop. Debounce approach: you know Chatty, she breaks down a whole story into pieces, sends them in one message after another. You wait until Chatty finishes the whole story: if she stops sending messages for 5 minutes, you would assume she has finished, now you check all.

debounging和Throttling是从一系列事件中选择目标以达到减少目标的目的。它们都需要一段时间作为参数,例如:x ms,以及后面/前面的变量来定义如何选择。

消除抖动

当x毫秒后没有其他事件发生时,选择事件

"--->": timeline  "o": event  "|===|": period (x=5)

--oo-o-----ooo-o----o-oo--oo-----o-o-ooo------> events
  |===|    |===|    |===|        |===|
  ||===|   ||===|   | |===|      | |===|   
  |  |===| | |===|  |  |===|     |   |===|
  |      | |   |===||     |===|  |    |===|
  |      | |       ||      |===| |     |===|
---------o---------o-----------o-----------o--> selected events (trailing)
--o--------o--------o------------o------------> selected events (leading)

节流

当有事件发生时,每x毫秒选择一个事件

"--->": timeline  "o": event  "|===|": period (x=5)

--oo-o-----ooo-o----o-oo--oo-----o-o-ooo------> events
  |===|    |===|    |===| |===|  |===||===|
------o--------o--------o-----o------o----o---> selected events (trailing)
--o--------o--------o-----o------o----o-------> selected events (leading)

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

关于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