来源
在开发过程中,经常会对一些事件进行监听,触发事件实现某些效果,但是某些事件如果触发特别频繁,会对性能上造成影响,以至于用户体验不好,比如:
鼠标事件:mousemove / mouseover
键盘事件:keypress / keyup
window: resize / scroll
用户频繁触发请求
这些情况下就需要用到throttle(节流)和 debounce(去抖),它们其实都是函数调用频率控制器。
区别
一个简单的比喻让我们了解下它们的区别:
我们上班、生活每天都需要坐电梯,用这个比喻再恰当不过了:
函数防抖和我们平时坐电梯差不多,如果有人进电梯(用户触发事件),那将在10秒钟后出发(执行程序),这时如果又有人进电梯了(用户在10秒内再次触发事件),我们又得等10秒再出发(重新计时)。
函数节流就比较直观了,有人进电梯,就开始计时,每10秒运送一次,如果没有人,则待机。
debouncing(去抖)
debounce的作用是,当调用动作触发一段时间后,才会执行该动作,若在这段时间间隔内又调用此动作则将重新计算时间间隔。
// debounce函数会维护一个timer,当同一函数在delay的时间间隔内再次触发,则清理timer,然后重新设置timer
var debounce = function(fn, delay) {
var timer = null;
return function() {
clearTimeout(timer);
timer = setTimeout(function() {
fn();
}, delay);
}
}
throttling(节流)
throttle只允许一个函数在规定的事件内执行一次。
// throttle会有一个阀值,当到达阀值的时候函数必定会执行一次
var throttle = function(fn, delay){
var statTime = 0;
return function() {
var currTime = new Date();
if (currTime - statTime > delay) {
fn();
statTime = currTime ;
}
}
}
使用场景
debounce:
- resize事件,通过拖拽浏览器窗口,可以触发多次resize事件
- 敲击键盘,通过ajax请求自动填充表单,只要求在输入完成后进行搜索
- 用户输入的验证,不在输入过程中处理,停止输入后进行验证时
throttle:
- dom的拖拽
- 用户输入的验证,不想停止输入再进行验证,而是每n秒进行验证时
- 无限滚动的页面,当滚动位置接近底部时,ajax请求更多内容
总结
两种函数在实际应用中要选择哪一个其实还是和使用场景和要求有关,具体情况具体分析。
debounce:将一系列迅速触发的事件减少为最后执行一次。
throttle:确保一个持续的操作以每几秒一次的速度执行。