谁能给我一个简单的解释,关于节流和debounging函数之间的区别,以限制速率的目的。
在我看来,两者的作用是一样的。我查看了这两个博客来找出答案:
http://remysharp.com/2010/07/21/throttling-function-calls
http://benalman.com/projects/jquery-throttle-debounce-plugin/
谁能给我一个简单的解释,关于节流和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
}
其他回答
这里真正重要的是,用最简单的话说:如果你有一些连续重复一段时间的操作(如鼠标移动,或页面大小调整事件),你需要运行一些函数来响应,但你不想对每个操作都做出反应(因为这可能会损害性能),你有两个选择:
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...
假设我们有一个回调函数“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次调用。
我个人认为反弹比油门更难理解。
因为这两个函数都可以帮助您延迟和降低某些执行的速度。假设您正在调用由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.
如何debound工作在硬件。
去噪是从数字信号中去除噪声的过程。当一个按钮被按下时,信号反弹会导致该按钮被注册为被按了多次。反弹消除了这种噪音,因此按钮只被记录为被按下一次。想象一把尺子在桌子边上弹跳,再想象开关里的金属触点像这样弹跳。
更好的是,看看这张图,显示了由弹跳引起的开关噪声。
我们使用适当计算额定值的电阻和电容来平滑信号n毫秒。
解释信号节流如何在硬件中工作。
信号节流是限制信号注册次数的过程。这通常用于防止一个按钮被注册为在短时间内被多次按下。
我更喜欢“门控”这个词,但那是因为我从事电子音乐制作。
我们在每个节流阀周期结束时打开闸门,并允许信号通过,然后再次关闭闸门,为下一个节流阀周期。
解释如何debounging工作在软件。
软件中的debound通常是通过使用定时器来实现的。当按钮被按下时,计时器开始。如果在计时器到期前再次按下按钮,计时器将被重置。这确保了按钮只能注册为每个弹跳周期被按下一次。
在debounce的许多实现中,我们创建了函数的debounce版本,该版本嵌入到包含计时器(或门)的闭包中。当计时器延迟过期时,我们再次将其设置为空。实际函数只在计时器为空时运行。通常,这意味着当我们第一次调用debpublished函数时,它将运行一次,然后对它的后续调用将有效地取消,直到延迟时间结束。
在debounce的某些实现中,当调用流被触发且计时器未过期时,计时器将重新启动。仅在反弹停止后调用该函数。这通常被称为尾随反弹。
解释在软件中节流是如何工作的。
软件中的节流通常是通过使用计数器来完成的。当按下按钮时,计数器增加。如果在计数器达到某一阈值之前再次按下按钮,计数器将复位。这限制了在给定的时间内按钮可以被注册为被按下的次数。最好把它想象成一个脉冲或节拍,当呼叫被发送到油门时,它会打开和关闭一个门。
速率限制是考虑节流阀的另一种方式。
为什么这是造成困惑的常见原因?
在许多用例中,debounce或throttle将为您带来您想要的结果,特别是如果您正在使用的软件实现允许您链接、跟踪或引导您的throttle / debounce。
尽管如此,我希望这里所有的答案和这个问题都能帮助你更清楚地理解。
它们非常相似。
一幅图胜过千言万语
节气门
防反跳
注意Debounce直到事件流停止才会触发。但是,Throttle会在每个间隔时间内触发一个事件。
(感谢css-tricks)