函数的 防抖和节流

435 阅读2分钟

函数防抖(等一段时间,然后带着一起做)

以送外卖举例

外卖员只送一家餐厅,每次餐厅来新订单,外卖员都会等5分钟,5分钟之内没有新订单,外卖员开始送餐
5分钟之内有新订单,外卖员会从新计时,直到5分钟内没有新订单,外卖员会把这段时间的订单一起送出

实际需求

持续触发不执行函数,不触发一段时间后再执行函数

思路

使用定时器,每次执行函数前看定时器是否存在,存在就清除定时器,不存在就执行函数

防抖函数 代码

function debounce(fn, delay){
  let timerId = null                           //声明定时器默认为空
  return function(){
    const context = this   
    if(timerId){window.clearTimeout(timerId)}  //如果定时器存在,清除定时器
    timerId = setTimeout(()=>{                 //定时器不存在,定时器等于在时间间隔后执行函数
      fn.apply(context, arguments)
      timerId = null                           //执行完函数取消定时器
    }, delay)
  }
}
const debounced = debounce(()=>console.log('hi'))
debounced()                                    //undefined
debounced()                                    //hi

函数节流 (一段时间内,执行一次后就不执行第二次,冷却时间)

以玩游戏举例

每次释放技能都有10秒的冷却时间,冷却时间内,不能再次释放技能

实际需求

持续触发并不会执行多次函数,到一定时间后再去执行函数

思路

通过设置一个开关,与setTimeout结合使用,表示是否可以执行函数

节流函数 代码

function throttle(fn, delay){
  let canUse = true                        //设置开关,true表示可以使用函数
  return function(){ 
    if(canUse){                            //如果可以使用,就调用函数
      fn.apply(this, arguments)
      canUse = false                       //函数执行后,把开关改为不可使用
      setTimeout(()=>canUse = true, delay) //在延迟时间后改为可以使用
    }
  }
}
const throttled = throttle(()=>console.log('hi'))
throttled()                                //hi
throttled()                                //undefined

总结

防抖和节流使用setTimeout来控制函数执行时机,可以节约性能,不至于多次触发复杂的业务逻辑而造成页面卡顿