概念理解
函数节流和函数防抖,两者都是优化高频率执行js代码的一种手段。
函数节流(throttle)与 函数防抖(debounce)都是为了限制函数的执行频次,以优化函数触发频率过高导致的响应速度跟不上触发频率,出现延迟,假死或卡顿的现象。
函数防抖(debounce)
当调用动作过n毫秒后,才会执行该动作,若在这n毫秒内又调用此动作则将重新计算执行时间
函数节流(throttle)
预先设定一个执行周期,当调用动作的时刻大于等于执行周期则执行该动作,然后进入下一个新周期
函数节流是指一定时间内js方法只跑一次。比如人的眨眼睛,就是一定时间内眨一次。这是函数节流最形象的解释。
函数防抖是指频繁触发的情况下,只有足够的空闲时间,才执行代码一次。比如生活中的坐公交,就是一定时间内,如果有人陆续刷卡上车,司机就不会开车。只有别人没刷卡了,司机才开车。
函数防抖和函数节流应用场景
以下场景往往由于事件频繁被触发,因而频繁执行DOM操作、资源加载等重行为,导致UI停顿甚至浏览器崩溃
window对象的resize、scroll事件
射击游戏中的mousedown、keydown事件
拖拽时的mousemove事件
文字输入、自动完成的keyup事件
实现最佳实践
实际上对于window的resize事件,实际需求大多为停止改变大小n毫秒后执行后续处理;而其他事件大多的需求是以一定的频率执行后续处理。针对这两种需求就出现了debounce和throttle两种解决办法。
函数防抖:函数防抖是让这个函数在执行上一次之后过了你规定的时间再执行的一种方法。以输入框为例,假设你要查询xxxx,你想实现当我输完了xxxx之后,再进行查询操作,那么你就需要用到函数防抖。
经典的函数防抖实践如下:
function throttle(method,context){
clearTimeout(method.tId)
method.tId = setTimeout(function(){
method.call(context)
},1000)
}
函数防抖(debounce)
防抖原理
通过定时器,在延时周期内,清除之前的DOM操作触发的处理函数,只执行最后一次的处理函数。
function _debounce(fn,wait){
var timer = null;
return function(){
clearTimeout(timer)
timer = setTimeout(()=>{
fn()
},wait)
}
}
function _log(){
console.log(1)
}
window.onscroll = _debounce(_log,500)
函数节流(throttle)
节流原理
要解决的问题是,避免处理函数被频繁的触发,让函数每隔一段时间执行一次,当在执行周期内被触发时,不允许被执行,所以直接为函数的执行添加时间间隔
function _throttle(fn,wait,time){
var previous = null; //记录上一次运行的时间
var timer = null;
return function(){
var now = +new Date();
if(!previous) previous = now;
//当上一次执行的时间与当前的时间差大于设置的执行间隔时长的话,就主动执行一次
if(now - previous > time){
clearTimeout(timer);
fn();
previous = now;// 执行函数后,马上记录当前时间
}else{
clearTimeout(timer);
timer = setTimeout(function(){
fn();
},wait);
}
}
}
function _log(){
console.log(1)
}
window.onscroll = _debounce(_log,500,2000)
使用方法
在jquery中使用:
$('input.user-name').on('input', debounce( () => {
//somecode
}, 800)
在vue中使用:
//Debounce.vue
methods:{
bindInputDebounce:debounce(function() {
console.log('bindInputDebounce')
})
}
参考文档:
https://segmentfault.com/a/1190000009675191#articleHeader5
https://segmentfault.com/a/1190000008768202
文章评论