摘要:定时器实现当触发事件的时候,我们设置一个定时器,再触发事件的时候,如果定时器存在,就不执行直到秒后,定时器执行执行函数,清空定时器,这样就可以设置下个定时器。当最后一次停止触发后,由于定时器的延迟,可能还会执行一次函数。
一、什么是防抖和节流
Ps: 比如搜索框,用户在输入的时候使用change事件去调用搜索,如果用户每一次输入都去搜索的话,那得消耗多大的服务器资源,即使你的服务器资源很强大,也不带这么玩的。
1. 防抖 - debounce其中一种解决方案就是每次用户停止输入后,延迟超过500ms时,才去搜索此时的String,这就是防抖。
原理:将若干个函数调用合成为一次,并在给定时间过去之后仅被调用一次。
代码实现:
function debounce(fn, delay) { // 维护一个 timer,用来记录当前执行函数状态 let timer = null; return function() { // 通过 ‘this’ 和 ‘arguments’ 获取函数的作用域和变量 let context = this; let args = arguments; // 清理掉正在执行的函数,并重新执行 clearTimeout(timer); timer = setTimeout(function() { fn.apply(context, args); }, delay); } } let flag = 0; // 记录当前函数调用次数 // 当用户滚动时被调用的函数 function foo() { flag++; console.log("Number of calls: %d", flag); } // 在 debounce 中包装我们的函数,过 2 秒触发一次 document.body.addEventListener("scroll", debounce(foo, 2000));
2. 节流 - throttledebounce函数封装后,返回内部函数
每一次事件被触发,都会清除当前的timer然后重新设置超时并调用。这会导致每一次高频事件都会取消前一次的超时调用,导致事件处理程序不能被触发
只有当高频事件停止,最后一次事件触发的超时调用才能在delay时间后执行
另一种解决方案比 防抖 要宽松些,这时我们不想用户一味的输入,而是给用户一些搜索提示,所以在当中限制每过500ms就查询一次此时的String,这就是节流。
原理:节流函数不管事件触发有多频繁,都会保证在规定时间内一定会执行一次真正的事件处理函数。
代码实现有两种,一种是时间戳,另一种是定时器
1)时间戳实现:
function throttle(func, delay){ let prev = Date.now(); return function(){ const context = this; const args = arguments; const now = Date.now(); if(now - prev >= delay){ func.apply(context, args); prev = Date.now(); } } }
当高频事件触发时,第一次应该会立即执行(给事件绑定函数与真正触发事件的间隔如果大于delay的话),而后再怎么频繁触发事件,也都是会每delay秒才执行一次。而当最后一次事件触发完毕后,事件也不会再被执行了。
2)定时器实现:
当触发事件的时候,我们设置一个定时器,再触发事件的时候,如果定时器存在,就不执行;直到delay秒后,定时器执行执行函数,清空定时器,这样就可以设置下个定时器。
fucntion throttle(func, delay){ let timer = null; return funtion(){ let context = this; let args = arguments; if(!timer){ timer = setTimeout(function(){ func.apply(context, args); timer = null; }, delay); } } }
当第一次触发事件时,肯定不会立即执行函数,而是在delay秒后才执行。
之后连续不断触发事件,也会每delay秒执行一次。
当最后一次停止触发后,由于定时器的delay延迟,可能还会执行一次函数。
3)综合使用时间戳与定时器,完成一个事件触发时立即执行,触发完毕还能执行一次的节流函数
function throttle(func, delay){ let timer = null; let startTime = Date.now(); return function(){ let curTime = Date.now(); let remaining = delay - (curTime - startTime); const context = this; const args = arguments; clearTimeout(timer); if(remaining <= 0){ func.apply(context,args); startTime = Date.now(); }else{ timer = setTimeout(func, remaining); } } }
需要在每个delay时间中一定会执行一次函数,因此在节流函数内部使用开始时间、当前时间与delay来计算remaining,当remaining <= 0时表示该执行函数了,如果还没到时间的话就设定在remaining时间后再触发。当然在remaining这段时间中如果又一次发生事件,那么会取消当前的计时器,并重新计算一个remaining来判断当前状态。
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/96518.html
摘要:若时间差大于间隔时间,则立刻执行一次函数。不同点函数防抖,在一段连续操作结束后,处理回调,利用和实现。函数防抖关注一定时间连续触发的事件只在最后执行一次,而函数节流侧重于一段时间内只执行一次。 原博客地址,欢迎star 函数防抖和节流 函数防抖和函数节流:优化高频率执行js代码的一种手段,js中的一些事件如浏览器的resize、scroll,鼠标的mousemove、mouseover...
摘要:概念函数防抖和函数节流,两者都是优化高频率执行代码的一种手段。防抖任务频繁触发的情况下,只有任务触发的间隔超过指定间隔的时候,任务才会执行。节流指定时间间隔内只会执行一次任务一定时间内方法只跑一次。 概念 函数防抖和函数节流,两者都是优化高频率执行js代码的一种手段。 防抖:任务频繁触发的情况下,只有任务触发的间隔超过指定间隔的时候,任务才会执行。 节流:指定时间间隔内只会执行一次任...
阅读 3080·2021-11-24 10:47
阅读 3831·2021-11-02 14:43
阅读 2228·2021-09-26 10:15
阅读 2253·2021-09-08 09:35
阅读 560·2019-08-30 12:45
阅读 2781·2019-08-29 17:04
阅读 3214·2019-08-26 14:05
阅读 1259·2019-08-26 12:10