场景:
如:浏览器的 resize、scroll、keypress、mousemove 等事件在触发时,会不断地调用绑定在事件上的回调函数,极大地浪费资源,降低前端性能。
为了优化体验,需要对这类事件进行调用次数的限制,对此我们就可以采用throttle(防抖)和debounce(节流)的方式来减少调用频率。
定义:
节流: n 秒内只运行一次,若在 n 秒内重复触发,只有一次生效
防抖: n 秒后在执行该事件,若在 n 秒内被重复触发,则重新计时
理解
节流:可以理解成MOBA游戏里英雄技能的cd,在cd中,技能(函数)只能触发一次,玩家连续点(多次触发函数)也无效果。
防抖:可以理解成MOBA游戏里英雄的回城,回城需要时间,计时完成后才能回到泉水(函数触发成功)若在回城时间内,再次点击回城(触发函数),则前次回城计时会被打断(前次函数被取消),重新计时下一轮回城。
防抖:
原理:利用给需要调用的函数设置定时器,在计时的时间内再次调用就取消掉这次的定时器,若无新的操作,则完成这次函数调用。
function debounce(fn,delay) {
let timeOut = null
return function(...arg){
if(timeOut){
clearTimeout(timeOut)
timeOut = null
}
timeOut = setTimeout(function(){
fn.apply(this,arg)
},delay)
}
}
节流:
原理:获取每次时间执行的时间与上一次执行的时间差,判断时间差是否超过设定的时间间隔,如果时间已经超过,则立即执行函数,如果没有超过,会取消后续的定时器任务,且最后一次时间的触发,是会执行的
function throttle(fn,delay){
let preTime = 0
let timeOut = null
return function(...arg){
let nowTime = data.now()
if(nowTime - preTime > delay){
preTime = nowTime
fn.apple(this,arg)
}else{
clearTimeout(timeOut)
timeOut = null
}
timeOut = setTimeout(()=>{
pre = data.now()
fn.apply(this,arg)
},delay)
}
}
区别
相同点:
都可以通过使用 setTimeout 实现
目的都是,降低回调执行频率。节省计算资源
不同点:
函数防抖,在一段连续操作结束后,处理回调,利用clearTimeout和 setTimeout实现。函数节流,在一段连续操作中,每一段时间只执行一次,频率较高的事件中使用来提高性能
函数防抖关注一定时间连续触发的事件,只在最后执行一次,而函数节流一段时间内只执行一次
例如,都设置时间频率为500ms,在2秒时间内,频繁触发函数,节流,每隔 500ms 就执行一次。防抖,则不管调动多少次方法,在2s后,只会执行一次。
应用场景
防抖在连续的事件,只需触发一次回调的场景有:
搜索框搜索输入。只需用户最后一次输入完,再发送请求
手机号、邮箱验证输入检测
窗口大小resize。只需窗口调整完成后,计算窗口大小。防止重复渲染。
节流在间隔一段时间执行一次回调的场景有:
滚动加载,加载更多或滚到底部监听
搜索框,搜索联想功能