手写 js函数防抖

1、什么是防抖

短时间内大量触发同一事件,只会执行一次函数。

函数防抖(debounce),指触发事件后在一定时间(比如 3 秒)内函数只能执行一次,如果这段时间(3 秒)内又触发了事件,则会重新计算函数执行时间。

2、为什么要防抖

我们在滚动屏幕的时候,一秒可以轻松出发多次事件,如果每次事件都请求数据,而且如果事件处理逻辑复杂,浏览器的压力会很大,输入框、滚动条的监听事件处理,如果不做防抖,每输入一个字或者滚动一下屏幕,都会请求数据,这样会造成性能浪费,用户体验也会很糟糕。

3、防抖原理

设置一个定时器约定在n毫秒后再触发事件处理,每次触发事件都会重新设置定时器,直到n秒内无第二次触发操作时,再执行函数。

  1. 第一次调用函数,创建一个定时器,在指定时间间隔之后运行代码
  2. 第二次调用函数,清除前一次的定时器,
  3. 如果前一个已经执行过了,则没有意义,如果尚未执行,将其替换成一个新的定时器,目的是只有在执行函数的请求停止了一段时间之后才执行。

4、手写防抖

function debounce(method, wait, immediate) {
  let timeout
  // debounced函数为返回值
  // 使用Async/Await处理异步,如果函数异步执行,等待setTimeout执行完,拿到原函数返回值后将其返回
  // args为返回函数调用时传入的参数,传给method
  let debounced = function(...args) {
    return new Promise (resolve => {
      // 用于记录原函数执行结果
      let result
      // 将method执行时this的指向设为debounce返回的函数被调用时的this指向
      let context = this
      // 如果存在定时器则将其清除
      if (timeout) {
        clearTimeout(timeout)
      }
      // 立即执行需要两个条件,一是immediate为true,二是timeout未被赋值或被置为null
      if (immediate) {
        // 如果定时器不存在,则立即执行,并设置一个定时器,wait毫秒后将定时器置为null
        // 这样确保立即执行后wait毫秒内不会被再次触发
        let callNow = !timeout
        timeout = setTimeout(() => {
          timeout = null
        }, wait)
        // 如果满足上述两个条件,则立即执行并记录其执行结果
        if (callNow) {
          result = method.apply(context, args)
          resolve(result)
        }
      } else {
        // 如果immediate为false,则等待函数执行并记录其执行结果
        // 并将Promise状态置为fullfilled,以使函数继续执行
        timeout = setTimeout(() => {
          // args是一个数组,所以使用fn.apply
          // 也可写作method.call(context, ...args)
          result = method.apply(context, args)
          resolve(result)
        }, wait)
      }
    })
  }

  // 在返回的debounced函数上添加取消方法
  debounced.cancel = function() {
    clearTimeout(timeout)
    timeout = null
  }

  return debounced
}

简单版

function debounce(func, wait) {
    let timeout = null
    return function() {
        let context = this
        let args = arguments
        if (timeout) clearTimeout(timeout)
        timeout = setTimeout(() => {
            func.apply(context, args)
        }, wait)
    }
}

猜你喜欢

转载自blog.csdn.net/Alive_tree/article/details/107863355