手写防抖节流

112 阅读2分钟

防抖

什么是防抖

频发触发某个事件,一定时间内没有再次触发,则只执行最后一次。如果规定时间内再次执行就重新开始计时。

防抖业务场景

比如搜索输入框,如果用户每次输入一个字符就发送一次请求,请求发送过于频繁。因此在用户停止输入的N秒以后发送请求。

手写防抖原理

  1. 定义函数,接收事件函数fn和防抖的规定等待时间wait
  2. 定义一个定时器
  3. 防抖函数的返回结果为一个函数。函数内部是fn的执行结果,使用apply方法将fn的执行上下文改为return的函数,并且传入参数。
  4. 使用settimeout延迟执行这个函数。
  5. 并且如果已经有定时器在执行这个函数,就清除定时器,保证函数只执行一次。

代码实现

function debounce(fn,wait){
  let timer;
  return function(){
    if(timer)clearTimeout(timer)
    timer = setTimeout(()=>{
      fn.apply(this,arguments);
    },wait)
  }

}

节流

什么是节流

将事件的频繁触发改为少量触发。执行一次以后,只有超过设定时间后再次触发才会执行下一次。

节流业务场景

  • 项目中,三级联动中,能够点击的选项过多,因此每次点击都会加载相应的组件。如果用户点击过快,浏览器没有足够时间解析,引发卡顿。
  • 或者一些频繁触发事件,onmousemove,鼠标滚动事件(scroll),窗口调整resize,疯狂抢购点击(click)。触发频率非常高,这时如果还伴随着向后台发送请求,会对服务器造成不必要的压力,还会造成页面卡顿

手写节流

第一种实现方式,利用时间戳

function throttle(fn, wait) {
  let previous = 0
  return function () {
    let now = Date.now();
    if (now - previous > wait) {
      fn.apply(this, arguments);
      previous = now;
    }

  }
}

第二种实现方式,利用定时器实现

function throttle(fn,wait){
  let timer = null
  return function(){
    if(!timer){
      timer = setTimeout(()=>{
        fn.apply(this,arguments)
        timer = null
      },wait)
    }
  }
}