前端基础知识之实现节流、防抖

284 阅读3分钟

今天我们来总结一下前端JS如何实现节流、防抖,给出例子并对节流、防抖的作用作出总结。相信大家一定玩过英雄联盟或者王者荣耀等 moba 类型游戏,游戏中有技能释放和回城这两大重要功能,我们以这两个功能为例解释节流和防抖。

节流 throttle

节流其实可以理解成技能冷却中,当我们使用技能后,通常会有一定的冷却时间。对应的,当用户进行一定的请求后,我们应该对请求的频率进行限制,防止用户短时间内多次请求。

我们先用伪代码来实现这一过程:

const throttle = (fn, time) => {
  let 冷却中 = false
  return (...args) => {
    if(冷却中) return
    fn.call(undefined, ...args)
    冷却中 = true
    setTimeout(()=>{
      冷却中 = false
    }, time)
  }
}

以上的例子就是一个可以给任何函数使用的节流函数。其中,我们通过输入参数 fn 和 time 来控制目标函数和节流时间,通过冷却中来实现计时器的功能。

  1. 先让 冷却中 = flase ,即表示技能没有在冷却,可以释放
  2. 再控制节流函数返回一个函数,返回的这个函数会接受节流函数传入的所有参数
  3. 加上一个判断,如果冷却中 = true,表示技能正在冷却,则请求中断,直接 return
  4. 否则,就执行目标函数,因为使用的是箭头函数,所以 this 为 undefined
  5. 冷却中 置为 true
  6. 最后接一个 setTimeout 函数,控制在 time 后才将计时器置为 true ,则在此期间,技能都是在冷却中,再次请求施放技能将被中断

将上述函数写成正确的形式就是节流的普通形式:

const throttle = (f, time) => {
  let timer = null
  return (...args) => {
    if(timer) {return}
    f.call(undefined, ...args)
    timer = setTimeout(()=>{
        timer = null
    }, time)
  }
}

防抖 debounce

理解了节流,防抖就更好理解了。防抖可以理解成回城功能,在回城期间是不能再次操作的,否则回城将被打断,计时器会重新计时。将上面过程写成伪代码如下:

const debounce = (fn, time) => {
  let 回城计时器 = null
  return (...args)=>{
    if(回城计时器 !== null) {
      clearTimeout(回城计时器) // 打断回城
    }
    // 重新回城
    回城计时器 = setTimeout(()=>{
      fn.call(undefined, ...args) // 回城后调用 fn
      回城计时器 = null
    }, time)
  }
}
  1. 类似节流,防抖函数也接受一个 fn 和 time
  2. 首先将回城计时器置为空
  3. 防抖函数返回一个函数,这个函数也接受防抖函数给的所有参数
  4. 如果此时回城计时器不为空,就表示正在回城,那么回城将被打断,然后进入后面重新回城
  5. 回城计时器等于一个 setTimeout 函数,当一段时间 time 过后的回城成功后调用一开始传入的 fn,然后将回城计时器置为空

写成普通的防抖函数形式为:

const debounce = (fn, time) => {
  let timer = null
  return (...args)=>{
    if(timer !== null) {
      clearTimeout(timer) 
    }
    timer = setTimeout(()=>{
      fn.call(undefined, ...args) 
      timer = null
    }, time)
  }
}

总结

最后是对节流和防抖使用场景的总结:

  1. 节流的使用能够避免用户频繁点击按钮,因为它会在计时的过程中直接中断再次的请求
  2. 防抖的使用能够避免用户频繁的拖动操作带来的多次更新页面,它会在用户最后一次操作结束后进行重新计时,计时器结束后才会执行

©本总结教程版权归作者所有,转载需注明出处