xxleyi / learning_list

聚集自己的学习笔记
10 stars 3 forks source link

debounce 防抖代码实现 #219

Open xxleyi opened 4 years ago

xxleyi commented 4 years ago

应对频繁发生事件的一种常见方式:在一段时间内,只在开始或结束时执行回调动作,其余时间保持静默,并且静默时段内被调用,静默期自动接续

  function debounce(func, wait, immediate) {
    let timeout

    return function() {
      // 提取动态作用域和函数入参
      const context = this
      const args = arguments

      // 延迟函数
      const later = function() {
        // 延迟函数内部清除延时器
        timeout = null
        // 非立即调用时,才真正执行
        if (!immediate) func.apply(context, args)
      }

      // 决定在定时器开始还是结束执行
      const shouldCallNow = immediate && !timeout

      // 清除此前延时器,并重新开始延时
      clearTimeout(timeout)
      timeout = setTimeout(later, wait)

      // 如果需要,则立刻执行
      if (shouldCallNow) func.apply(context, args)
    }
  }

其它功能的添加,可以基于此继续改进,比如添加取消功能:

  function debounce(func, wait, immediate) {
    let timeout

    const debounced = function() {
      // 提取动态作用域和函数入参
      const context = this
      const args = arguments

      // 延迟函数
      const later = function() {
        // 延迟函数内部清除延时器
        timeout = null
        // 非立即调用时,才真正执行
        if (!immediate) func.apply(context, args)
      }

      // 决定在定时器开始还是结束执行
      const shouldCallNow = immediate && !timeout

      // 清除此前延时器,并重新开始延时
      clearTimeout(timeout)
      timeout = setTimeout(later, wait)

      // 如果需要,则立刻执行
      if (shouldCallNow) func.apply(context, args)
    }

    debounced.cancel = () => {
      clearTimeout(timeout)
      timeout = null
    }

    return debounced
  }