上图是对鼠标进行监听,事件执行的很频繁,如果执行的事件是对接口的请求,那么会在短时间内发起大量重复请求,所以我们需要防抖或者节流进行解决。
防抖
防抖即为事件触发n秒后才执行事件,如果在n秒内又触发事件则重新计时
1. 手写版
1 2 3 4 5 6 7 8 9
| function debounce(func, wait) { let timer = null; return () => { clearTimeout(timer); timer = setTimeout(()=> { func.apply(this, arguments) }, wait); } }
|
移动完n秒后才执行事件
2. 可立即执行版
触发事件立即执行,停止n秒后才可以重新触发
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| function debounce(func, wait, immediate = true) { let timer;
return () => { if (timer) clearTimeout(timer); if (immediate) { var callNow = !timer; timer = setTimeout(() => { timer = null; }, wait) if (callNow) func.apply(this, arguments); } else { timer = setTimeout(() => { func.apply(this, arguments); }, wait); } } }
|
节流
节流即为连续触发事件但是在n秒中只执行一次函数
1. 时间戳版
1 2 3 4 5 6 7 8 9 10 11
| function throttle(func, wait) { var previous = 0;
return () => { var now = new Date(); if (now - previous > wait) { func.apply(this, arguments); previous = now; } } }
|
当鼠标移入的时候,事件立刻执行,每过1s会执行一次,如果在2.2s停止触发,之后不会再执行事件。
2. 定时器版
1 2 3 4 5 6 7 8 9 10 11 12 13
| function throttle(func, wait) { var timeout; var previous = 0;
return () => { if (!timeout) { timeout = setTimeout(() => { timeout = null; func.apply(this, arguments) }, wait) } } }
|
可以看到使用定时器版本的节流函数,鼠标移入并不会立即执行,此后每移动1秒执行一次函数,在3.2秒左右移出鼠标,但是仍会在4秒时执行函数
参考
https://github.com/mqyqingfeng/Blog/issues/22
https://github.com/mqyqingfeng/Blog/issues/26