函数节流与去抖

在以往的项目中,为了防止频繁触发事件请求,我通常只是给事件函数上一把“锁”(Boolean值),或者修改<input>disable属性,当事件执行完成后再“解锁”。然而,面对一些异常情况,如ajax长时间得不到浏览器响应,导致无法“解锁”,事件被永远封印。函数节流(throttle)与去抖(debounce)避免了这种情况发生。

简介

对于resize,scroll,keydown,keyup,keypress,mousemove等事件十分容易被用户连续多次触发,导致事件绑定的回调函数短时间内不断被重复执行(其中大部分是不必要甚至恶性的),既增加了浏览器的负担,也影响了用户体验效果。函数节流(throttle)与去抖(debounce)的出现对此进行了良好的优化,减少同一事件短时间内的重复触发。

throttle

原理

当第一次触发事件后,先执行事件对应的回调函数,然后进入一段计时。在这段计时事件内再次触发的该事件将被忽略,直到计时结束后才能再次触发并进入新的计时。

简易实现

通过闭包避免全局变量对全局环境造成污染。

1
2
3
4
5
6
7
8
9
10
11
12
13
function throttle(callback, time) {
let timer = null;

return function() {
if (!timer) {
callback();
timer = setTimeout(() => {
clearTimeout(timer);
timer = null;
}, time);
}
}
}

debounce

原理

当触发事件后并不会立即执行事件,而是开始计时,计时结束之前如果事件再次被触发则抛弃之前的任务,重新开始计时,直到事件稳定不再被重复触发时,计时结束后执行事件绑定函数。

简易实现

1
2
3
4
5
6
7
8
9
10
function debounce(callback, time) {
let timer = null;

return function() {
clearTimeout(timer);
timer = setTimeout(() => {
callback();
}, time);
}
}

参考

《JavaScript高级程序设计》
《debounce与throttle区别》