防抖和节流
本质上是优化⾼频率执⾏代码的⼀种⼿段
如:浏览器的 resize 、 scroll 、 keypress 、 mousemove 等事件在触发时,会不断地调⽤
绑定在事件上的回调函数,极⼤地浪费资源,降低前端性能
为了优化体验,需要对这类事件进⾏调⽤次数的限制,对此我们就可以采⽤ 防抖(debounce) 和 节
流(throttle) 的⽅式来减少调⽤频率
节流: n 秒内只运⾏⼀次,若在 n 秒内重复触发,只有⼀次⽣效
• 将时间戳写法的特性与定时器写法的特性相结合,实现⼀个更加精确的节流
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| 1 function throttled(fn, delay) { 2 let timer = null 3 let starttime = Date.now() 4 return function () { 5 let curTime = Date.now() // 当前时间 6 let remaining = delay - (curTime - starttime) // 从上⼀次到现在,还剩下多 少多余时间 7 let context = this 8 let args = arguments 9 clearTimeout(timer) 10 if (remaining <= 0) { 11 fn.apply(context, args) 12 starttime = Date.now() 13 } else { 14 timer = setTimeout(fn, remaining); 15 } 16 } 17 }
|
防抖: n 秒后在执⾏该事件,若在 n 秒内被重复触发,则重新计时
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| 1 function debounce(func, wait, immediate) { 2 let timeout; 3 return function () { 4 let context = this; 5 let args = arguments; 6 if (timeout) clearTimeout(timeout); // timeout 不为null 7 if (immediate) { 8 let callNow = !timeout; // 第⼀次会⽴即执⾏,以后只有事件执⾏后才会再次触 发 9 timeout = setTimeout(function () { 10 timeout = null; 11 }, wait) 12 if (callNow) { 13 func.apply(context, args) 14 } 15 } 16 else { 17 timeout = setTimeout(function () { 18 func.apply(context, args) 19 }, wait); 20 } 21 } 22 }
|
相同点:
都可以通过使⽤ setTimeout 实现
⽬的都是,降低回调执⾏频率。节省计算资源
不同点:
函数防抖,在⼀段连续操作结束后,处理回调,利⽤ clearTimeout 和 setTimeout 实现。
函数节流,在⼀段连续操作中,每⼀段时间只执⾏⼀次,频率较⾼的事件中使⽤来提⾼性能
函数防抖关注⼀定时间连续触发的事件,只在最后执⾏⼀次,⽽函数节流⼀段时间内只执⾏⼀次

防抖在连续的事件,只需触发⼀次回调的场景有:
•
搜索框搜索输⼊。只需⽤⼾最后⼀次输⼊完,再发送请求
•
⼿机号、邮箱验证输⼊检测
•
窗⼝⼤⼩ resize 。只需窗⼝调整完成后,计算窗⼝⼤⼩。防⽌重复渲染。
节流在间隔⼀段时间执⾏⼀次回调的场景有:
•
滚动加载,加载更多或滚到底部监听
•
搜索框,搜索联想功能