JS常用的方法--节流防抖

108 阅读2分钟
防抖(debounce)

触发事件时,相对应的函数不会立即执行,而是推迟一段时间后执行,在频繁触发事件时,只要每次触发的时间是在规定内那么就只会执行最后一个函数。

防抖的使用场景
  1. 输入框中频繁的输入内容,搜索或者提交信息;
  2. 频繁的点击按钮,触发某个事件;
  3. 监听浏览器滚动事件,完成某些特定操作;
  4. 用户缩放浏览器的resize事件...
节流(throttle)

触发事件时,按照某个时间频率触发函数,在频繁触发的时候只有到固定时间才会触发函数,无论在固定时间内触发多少次只会在时间到才执行函数。

节流的使用场景
  1. 监听页面的滚动事件;
  2. 鼠标移动事件;
  3. 用户频繁点击按钮操作;
  4. 游戏中的一些设计...
防抖函数
/*
* @param fn 待执行的函数
* @param delay 延迟时长
* @param immediate 立即执行
* @param resultCallback 回调函数
* */
function debounce(fn, delay, immediate = false, resultCallback) {
  // 1.定义一个定时器, 保存上一次的定时器
  let timer = null
  let isInvoke = false
  // 2.真正执行的函数
  const _debounce = function (...args) {
    // 取消上一次的定时器
    if (timer) clearTimeout(timer)
    // 判断是否需要立即执行
    if (immediate && !isInvoke) {
      const result = fn.apply(this, args)
      if (resultCallback) resultCallback(result)
      isInvoke = true
    } else {
      // 延迟执行
      timer = setTimeout(() => {
        // 外部传入的真正要执行的函数
        const result = fn.apply(this, args)
        if (resultCallback) resultCallback(result)
        isInvoke = false
        timer = null
      }, delay)
    }
  }
  // 封装取消功能
  _debounce.cancel = function () {
    if (timer) clearTimeout(timer)
    timer = null
    isInvoke = false
  }
  return _debounce
}
节流函数
/*
* @params fn 待执行函数
* @params interval 固定时间
* @params leading  是否执行首个
* @params trailing 是否执行最后一个
* */

function throttle(fn, interval, options = { leading: true, trailing: false }) {
  // 1.记录上一次的开始时间
  const { leading, trailing, resultCallback } = options
  let lastTime = 0
  let timer = null

  // 2.事件触发时, 真正执行的函数
  const _throttle = function(...args) {
    // 2.1.获取当前事件触发时的时间
    const nowTime = new Date().getTime()
    if (!lastTime && !leading) lastTime = nowTime
    // 2.2.使用当前触发的时间和之前的时间间隔以及上一次开始的时间, 计算出还剩余多长事件需要去触发函数
    const remainTime = interval - (nowTime - lastTime)
    if (remainTime <= 0) {
      if (timer) {
        clearTimeout(timer)
        timer = null
      }
      // 2.3.触发函数
      const result = fn.apply(this, args)
      if (resultCallback) resultCallback(result)
      // 2.4.保留上次触发的时间
      lastTime = nowTime
      return
    }
    if (trailing && !timer) {
      timer = setTimeout(() => {
        timer = null
        lastTime = !leading ? 0: new Date().getTime()
        const result = fn.apply(this, args)
        if (resultCallback) resultCallback(result)
      }, remainTime)
    }
  }

  _throttle.cancel = function() {
    if(timer) clearTimeout(timer)
    timer = null
    lastTime = 0
  }

  return _throttle
}

第三方库(Underscore.js) (www.underscorejs.com.cn/)