-
323 这个 是一个很好的可视化 – 提琴 评论 2014年9月23日9:31 -
非常简单的例子帮助我理解。 jsfiddle.net/Voronar/sxjy25ew/1 – 基里尔·哈利托夫 评论 2017年5月22日9:36 -
7 也可以在这里看到可视化效果 codepen.io/chriscoyier/pen/vOZNQV代码 – 特朗沃斯 评论 2017年7月4日10:23 -
有关节流和反弹的简单和普通JS实现,请参阅 我的答案 在 js中的简单油门 . – 秋葵 评论 2018年7月24日7:43 -
三 我不喜欢链接个人网站,因为历史表明,大多数个人网站总有一天会离线。 因此,我已经录制了尼穆斯的去抖动演示,这样,如果它在未来消失了,人们仍然可以在这里看到它: imgur.com/PkwDnfy网站 – 阿德纳 评论 2021年10月1日8:18
27个答案
节流 将延迟执行函数。 它将减少多次触发事件的通知。 辩论 将对函数的一系列连续调用组合成对该函数的单个调用。 它确保对多次触发的事件发出一个通知。
-
18 我认为thriqon的可视化链接显示了它的工作原理。 如果您有一个函数被多次调用,例如,当发生调整大小或鼠标移动事件时,它可以被多次调用。 如果您不想这样做,可以对其进行节流,以便定期调用该函数。 辩论意味着它将在一系列通话的末尾(或开始)被调用。 – 多纳尔 评论 2014年9月23日9:45 -
1 -
25 -
2 -
7
节气门 :原始函数在指定的时间段内最多调用一次。 辩论 :原始函数将在 调用方在指定的时间段后停止调用修饰函数 .
//返回一个函数,只要它继续被调用,就不会 //被触发。 函数停止调用后将被调用 //N毫秒。 如果传递了“immediate”,则在 //前缘,而不是后缘。 _.deboush=函数(func,wait,immediate){ var超时; 返回函数(){ var上下文=此,args=参数; var later=函数(){ 超时=空; if(!immediate)func.apply(context,args); }; var callNow=立即&&! 超时; clearTimeout(超时); timeout=setTimeout(稍后,等待); if(callNow)func.apply(context,args); }; };
天真 方法:只要消息到达,就检查每条消息。 当应用程序图标反弹时,请选中。 这不是最有效的方法,但你总是最新的。 节气门 方法:每5分钟检查一次(如果有新的)。 当新消息到达时,如果您在过去5分钟内的任何时候进行了检查,请忽略它。使用这种方法可以节省时间,同时仍在循环中。 辩论 方法:你知道Chatty,她把整个故事分解成几部分,用一条接一条的信息发送出去。 你要等到Chatty写完整个故事:如果她停止发送消息5分钟,你会认为她已经写完了,现在你检查一下。
差异
用例说明
搜索栏 :不想在用户每次按下键时都进行搜索吗? 想在用户停止输入1秒后进行搜索吗? 使用 消除颤抖 按键1秒。 射击游戏 :手枪在每次射击之间需要1秒的时间,但用户在1秒内多次单击鼠标。 使用 节气门 鼠标单击可确保过早的单击被忽略。
颠倒他们的角色
在搜索栏上限制1秒 :如果用户键入“abcdefghij”,每个后续字符每隔0.6秒键入一次,则 节气门 将在第一次按下“a”时触发。 然后,它将在接下来的1秒内忽略每次按下; 即0.6秒标记处的“b”将被忽略。 然后,1.2秒时的“c”将再次触发搜索,然后再次重置时间,依此类推,以获取后续按键(例如,1.8秒的“d”将被忽略,但2.4秒的“e”将被触发,等等)。 辩论手枪1秒 :当用户看到敌人时,他会单击鼠标,但不会射击。 他会在那一秒钟内再次点击几次,但仍不会射门。 只有在停止咔嗒声整整一秒钟后,手枪才会最终射出一枪。
“现实生活”比较
-
4 -
-
2 @Rivenfall Throttle and Deboush是为了降低噪音而设计的,所以它们是为了减少一些人的伤亡。 他们有不同的人员流失策略。 你要找的是延迟运算符[ rxjs.dev/api/operators/delay] 。这只会延迟他们的反应。 延迟高德将是正常的守卫,只是对他来说,语音处理需要5秒。因此,除了5秒的延迟外,将允许所有延迟。 – 阿米蒂加 评论 2022年12月17日7:03 -
1 这不太正确。 辩论可以随时进行,也可以不拖延。 如果你直接去抖动你的函数,就会有延迟。 要无延迟地解抖函数,请写入 如果 旗帜 为true,运行我的函数,然后设置 旗帜 到false ,然后解抖将标志设置回true的语句。 也许还有一个词可以用来形容这个,而不是“放松”? – 兰尼·海德布雷德 评论 2022年12月20日22:21 -
1
它比演示要简单。
如果用户“停止键入”,则自动保存或验证文本字段的内容:在确定用户不再键入(不再按键)后,操作将只执行一次。 记录用户放置鼠标的位置:用户不再移动鼠标,因此可以记录(最后)位置。
v-sync的实现基于节流:只有在上次屏幕绘制后经过16ms时,才会绘制屏幕。 无论调用多少次屏幕刷新功能,它最多每16ms运行一次。
-
1 -
9 -
1
谈话 .你等对方说完后再回复。 油门=鼓形钻头 你只能在一个简单的4/4鼓位上弹奏音符。
打字。 你想在用户停止输入后做点什么。 因此,在最后一次击键后等待1秒是有意义的。 每次击键都会重新开始等待。 动画。 当用户停止悬停在某个元素上时,您希望缩小该元素。如果不使用去抖动,可能会由于光标无意中在“热”区和“冷”区之间移动而导致动画不稳定。
滚动。 您希望对滚动作出反应,但限制计算量,因此每100毫秒执行一次操作就足以防止潜在的延迟。 鼠标移动。 与滚动相同,但用于鼠标移动。 API调用 您希望对某些UI事件触发API调用,但希望限制API调用的数量,以避免服务器过载。
功能去抖动(fn,延迟){ let句柄=null 返回函数(){ if(手柄){ handle=清除超时(handle) } 句柄=设置超时(()=>{ fn(…参数) },延迟) } }
功能节流阀(fn,延迟){ let句柄=空 let prevArgs=未定义 返回函数(){ prevArgs=参数 if(!句柄){ fn(…prevArgs) prevArgs=空 句柄=setInterval(()=>{ if(!prevArgs){ handle=clearInterval(句柄) }其他{ fn(…prevArgs) prevArgs=空 } },延迟) } } }
更新日期1-20-23
功能节流阀(fn,延迟){ 让canFire=true 让队列=[] 函数pop(){ if(queue.length<1)返回 const[that,args]=队列.pop() fn.apply(即args) canFire=错误 设置超时(()=>{ canFire=真 pop() },延迟) } 函数push(){ queue.push([this,arguments]) if(canFire)pop() } push.cancel=()=>{ 队列=[] } 回推 }
更新日期:11-09-23
功能节流阀(fn,延迟){ 让h 让队列=[] 函数pop(){ if(queue.length<1)返回 如果(!h){ const[that,args]=队列.pop() fn.apply(即args) h=设置超时(()=>{ h=空 pop() },延迟) } } 返回函数push(){ queue.push([this,arguments]) pop() } }
Throttling强制执行函数的最大调用次数 加班。 如“最多每100次执行此功能 毫秒。 “说在正常情况下你会这么说 在10秒内运行1000次。 如果你只把它节流一次 每100毫秒,它最多只能执行100个函数 次
(10s*1000)=10000ms 10000ms/100ms节流=最多100次呼叫
辩论强制要求函数在 一段时间过去了,却没有被调用。 如中所示 “只有在100毫秒后才执行此函数 被呼叫。 "
节流 :节流为(100ms)时,“cb”为 被调用【第100毫秒、第200毫秒、第300毫秒、……第1000毫秒】。 这是每100毫秒1次呼叫。 这里1000个对“cb”的调用优化为10个调用。 辩论 :在(100ms)的去抖动情况下,“cb”只会在[1100秒]调用一次。 这是在[1000th ms]发生的“E”最后一次触发后100毫秒。 这里1000个对“cb”的调用优化为1个调用。
辩论
“-->”:时间线 “o,c,e”:事件,其中 “o”是由“leading”选择的事件 “e”是通过“尾随”选择的事件 “c”是跳过的事件 “|===|”:句点(x=5)
--oc-e-----occ-e----o-cc-ce-----o-c-cce----->源事件 |===| |===| |===| |===| ||===| ||===| | |===| | |===| | |===| | |===| | |===| | |===| | | | |===|| |===| | |===| | | | || |===| | |===| --o---------o----------o-----------o---------->所选事件(前导) ---------e----------e---------e-----------e-->所选事件(尾随)
节流
--oc-e-----occ-e---o-ce--oe------o-c-eoe------>源事件 |===| |===| |===| |===| |===||===| --o--------o--------o-o---------o---------o-o------>所选事件(前导) ------e---------e---------e-e-------e--------e-e---e-->所选事件(尾随)
函数去抖动(func,wait){ 让超时 return(…arg)=>{ clearTimeout(超时); timeout=setTimeout(()=>函数应用(this,arg),等待) } } 函数SayHello(){ console.log(“耶稣在说你好!!”) } 让x=放松(SayHello,3000) x()
函数调节(回调、间隔){ 让enableCall=true; return(…args)=>{ if(!enableCall)return; enableCall=false; 回调.apply(this,args); setTimeout(()=>enableCall=true,interval); } } 函数helloFromThrottle(){ log(“耶稣在打招呼!!!”) } const foo=油门(helloFromThrottle,5000) foo()
去抖动是如何在硬件中工作的。
解释信号节流在硬件中是如何工作的。
解释去抖动在软件中是如何工作的。
解释节流在软件中的工作原理。
为什么这是一个常见的混淆原因?
节流是我们在给定时间内触发函数的方式。 第一个请求被允许通过。 原始函数每指定时间只执行一次
const trottle=函数(fn,d){ let标志=true;// 通过第一项比赛 返回函数(){ if(标志){ fn();// 执行装饰功能 flag=false;// 阻止下一个激发的事件 设置超时(()=>{ 标志=true;// 在指定延迟后取消阻止下一个激发的事件 },d); } }; };
辩论是一种阻止函数在最近被调用时被调用的方法。 只允许通过最后一个请求。 只有当调用方在指定的时间内停止调用修饰函数时,才会执行原始函数。
常数去抖=函数(fn,d){ 让计时器; 返回函数(){ clearTimeout(计时器);// 如果事件被延迟触发,则清除/重置计时器 timer=setTimeout(()=>{//执行函数 fn(); },d); }; };
这个(节流)和去抖动之间的主要区别是节流保证了函数的定期执行,至少每X毫秒执行一次。
const throttle=(回调,时间=0)=>{ 设throttle_req,count=0; 返回异步函数(){ var上下文=此,args=参数; if(throttle_req)返回; throttle_req=真; 如果(时间>0) { callback.apply(上下文,参数); 设置超时(()=>{ throttle_req=假; },时间||200) } 其他的 { let response=等待callback.apply(context,args); throttle_req=假; 返回响应; } } } 常量去抖动=(回调,时间=0)=>{ 让债务_req; 返回函数(){ var上下文=此,args=参数; 清除超时(debounce_req) debounce_req=设置超时(()=>{ debounce_req=空; callback.apply(上下文,参数); },时间||200) } }
var throttleFunct=油门(功能(num){ console.log(num,“hello throttle”) }, 2000); throttleFunct(300)//它执行。 因为这是第一次呼叫 throttleFunct(400)//它不会执行
var getDataAsync=节流阀(函数(id,name){ return new Promise((resolve)=>{ 设置超时(()=>{ 解析({name:name,id:id}) }, 2000) }) }); 异步函数测试(){ let response=等待getDataAsync(120,'Sherrey')。然后(resp=>resp) log(响应,“response”)//它执行。 因为这是第一个电话 response=等待getDataAsync(120,'James')。然后(resp=>resp) console.log(response,“responsd2”)//它在第一次请求后执行2 response=等待getDataAsync(120,'Jonathan').then(resp=>resp) log(response,“respond3”)//它在第二个请求后执行3 } 测试()
var debounceFunct=debounce(函数(num){ 控制台.log(num+1) }, 2000); debounceFunct(300)//它不会执行并且被取消 debounceFunct(400)//它执行并替换为前一个调用。 因为这是最新的火灾事件
去抖动-跳过所有传入动作, 除了最后一个(“最后一个”是由您为去抖动功能设置的“等待”时间段定义的,例如,2s-它会认为操作洪水停止,如果在2s内没有采取任何操作,那么它会做出反应。如果您不关心定期更新,那么这个策略是合理的,您只需要至少做出一次反应。 节流-如果你想“按计划”做出反应,即使动作泛滥无止境,也要定期更新,你可以让函数以固定的间隔运行(不再频繁,然后是指定的时间间隔),例如,2s节流意味着如果采取了动作,你的响应将执行一次,但不少于2秒。 因此,随着连续动作的泛滥,你的响应将在0s、2s、4s、6s、8s上运行。。。