# 防抖

防抖:不管事件触发频率多高,一定在事件触发 n 秒后才执行,如果在一个事件执行的 n 秒内又触发了这个事件,就以新的事件的时间为准,n 秒后才执行,总之,触发完事件 n 秒内不再触发事件,n 秒后再执行。

function debounce(fn, wait, immediate) {
  let timer = null
  return function (...args) {
    clearTimeout(timer)
    // 是否立即执行一次
    if (immediate && !timer) {
      fn.apply(this, args)
    }

    timer = setTimeout(() => {
      fn.apply(this, args)
    }, wait)
  }
}

通过闭包保存一个标记(timer)来保存 setTimeout 返回的值, 每当要触发函数的时候, 需要先把上一个 setTimeout 清除掉, 然后再创建一个新的 setTimeout, 这样就能保证执行函数后的 wait 间隔内如果还要触发函数, 就不会执行 fn

# 使用场景

  • 监听 resize 或 scroll,执行一些业务处理逻辑
window.addEventListener('resize', debounce(handleResize, 200))
window.addEventListener('scroll', debounce(handleScroll, 200))

window 的 resize、scroll, mousedown、mousemove, keyup、keydown 等高频触发的事件

  • 搜索输入框,在输入后 200 毫秒搜索
debounce(fetchSearchData, 200)

函数防抖是 在事件触发 n 秒后才执行,在监听 scroll 事件和 resize 事件时,只要 n 秒后才执行一次就可以了,不需要每次只要一触发 scroll 或 resize 的时候就执行,n 秒内的执行是没有意义的(用户可能都感受不到,而且很容易造成卡顿)。

Last Updated: 1/21/2022, 6:09:58 PM