防抖(debounce) & 节流(throttle)

防抖(debounce)

  1. 定义: 在规定的时间内如果事件被密集触发,则规定的时间重新计算并且规定的时间结束后只触发最后一次事件。
  2. 应用场景:
    (1) 输入框中频繁的输入内容,搜索或者提交信息
    (2) 频繁的点击按钮,触发某个时间
    (3) 监听浏览器滚动事件,完成某些特定操作
    (4) 用户缩放浏览器的resize事件
function debounce(fn, delay, immediate = false, resultCb) {
let timer = null
// 定义是否执行过
let isInvoke = false
// 不能用箭头函数,否则this指向声明的作用域
const _debounce = function(...args) {
  if (immediate && !isInvoke) {
    const res = fn.apply(this, args)
    if (resultCb) {
      resultCb(res)
    }
    isInvoke = true
  } else {
    if (timer) clearTimeout(timer)
    timer = setTimeout(() => {
      // 绑定触发对象的this和事件参数
      const res = fn.apply(this, args)
      if (resultCb) {
        // 回调传递返回值
        resultCb(res)
      }
      timer = null
      // 设置为false下次事件第一次输入仍然是立即执行
      isInvoke = false
    }, delay)
  }
}
// 取消功能 函数也是一个对象,可以挂载一个方法
_debounce.cancel = function() {
  if (timer) clearTimeout(timer)
  timer = null
  isInvoke = false
}
return _debounce
}

节流(throttle)

  1. 定义: 在规定的一段时间内密集触发事件,事件只会触发一次,并且这段时间只有完全结束后才会重置( 一般都是执行规定时间内第一次触发的事件 )
  2. 应用场景:
    (1) 监听页面的滚动事件
    (2) 鼠标移动事件
    (3) 用户频繁点击按钮操作
    (4) 游戏中的一些设计( 飞机大战发射子弹 )
    function throttle(fn, interval, options = {
  leading: true,
  trailing: false
}) {
  // 上一次开始时间,默认为0
  const {
    leading = true,
      trailing = false
  } = options
  let lastTime = 0
  let timer = null
  const _throttle = function(..args) {
    // 每次触发时的当前时间
    const nowTime = new Date().getTime()
    // 如果是第一次进入并且不希望一开始就执行(leading === false)
    if (lastTime === 0 && leading === false) {
      lastTime = nowTime
    }
    // 计算剩余期间
    const remainTime = interval - (nowTime - lastTime)
    if (remainTime <= 0) {
      // 如果有真正执行的函数,则不需要触发同一期间内非第一次执行的函数
      if (timer) {
        clearTimeout(timer)
        timer = null
      }
      // 如果剩余期间小于等于0执行事件函数
      fn.apply(this, args)
      // 将本次当前时间设置为最后一次触发时间,进入下一个周期
      lastTime = nowTime
      return
    }
    // 范围期间内非第一次输入的值是否执行
    if (trailing && !timer) {
      // 只需要一个定时器
      timer = setTimeout(() => {
        timer = null
        lastTime = !leading ? 0 : new Date().getTime()
        fn.apply(this, args)
      }, remainTime)
    }
  }
  _throttle.cancel = function() {
    if (timer) {
      clearTimeout(timer)
      timer = null
      lastTime = 0
    }
  }
  return _throttle
}

本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!