网上很多节流防抖的写法都是错的,看这里!【防抖】

213 阅读1分钟

网上很多节流防抖的写法都是错的,不想大家被误导,看这里吧,正解!

防抖(debounce)

普通版

普通版防抖是在满足要求后最后才执行一次。常见场景是输入查询

// 普通版
function debounce (fn, wait) {
  let timer = null
  return function (...args) {
    const context = this
    if (timer) {
      clearTimeout(timer)
    }
    timer = setTimeout(() => {
      fn.apply(context, args)
    }, wait)
  }
}

立即执行版

立即执行版是立即就执行,最后不再执行。总的还是执行一次。常见场景是提交按钮

举例说明:一个提交按钮,假如1s内连续点击不执行,如果用户连续点击10s(点击间隔都没有超过1s),那么【普通版】会在第11s结束时才执行,【立即执行版】会在第一次点击后立马执行,最后不执行。

// 立即执行版
function debounce (fn, wait) {
  let timer = null
  return function (...args) {
    const context = this
    if (timer) {
      clearTimeout(timer)
    }
    const canRun = !timer
    timer = setTimeout(() => {
      timer = null
    }, wait)
    if (canRun) {
      fn.apply(context, args)
    }
  }
}

混合版

可以根据用户需要使用上面2个版本哪一个,通过一个参immediate控制。

/**
 * @desc 函数防抖
 * @param fn 函数
 * @param wait 延迟执行毫秒数
 * @param immediate true 表立即执行,false 表非立即执行
 */
function debounce (fn, wait, immediate) {
  let timer = null
  return function (...args) {
    const context = this
    if (timer) {
      clearTimeout(timer)
    }
    if (immediate) {
      const canRun = !timer
      timer = setTimeout(() => {
        timer = null
      }, wait)
      if (canRun) {
        fn.apply(context, args)
      }
    } else {
      timer = setTimeout(() => {
        fn.apply(context, args)
      }, wait)
    }
  }
}

混合版,带取消功能

/**
 * @desc 函数防抖
 * @param fn 函数
 * @param wait 延迟执行毫秒数
 * @param immediate true 表立即执行,false 表非立即执行
 */
function debounce (fn, wait, immediate) {
  let timer = null
  const debounceFn = function (...args) {
    const context = this
    if (timer) {
      clearTimeout(timer)
    }
    if (immediate) {
      const canRun = !timer
      timer = setTimeout(() => {
        timer = null
      }, wait)
      if (canRun) {
        fn.apply(context, args)
      }
    } else {
      timer = setTimeout(() => {
        fn.apply(context, args)
      }, wait)
    }
  }
  debounceFn.cancel = () => {
    if (timer) {
      clearTimeout(timer)
      timer = null
    }
  }
  return debounceFn
}