javaScript防抖和节流

62 阅读2分钟

防抖函数(Debounce)

防抖函数通常是事件被触发后,等待一段时间,若这段时间内没有事件被触,则实行函数,如果等待的这段时间内事件再次被触发,则等待的事件重置。常用场景:监听输入事件、防止用户多次点击按钮。

封装:

/**
 * 创建一个防抖函数,用于限制函数的执行频率
 * 如果在等待时间内再次被调用,先前的调用将被取消,并重新计算等待时间
 *
 * @param {Function} fn 要进行防抖处理的函数
 * @param {number} delay 延迟执行的时间,单位为毫秒
 * @param {boolean} immediate 是否在第一次调用时立即执行函数,若为true,则在等待时间结束后执行
 * @returns {Function} 返回防抖处理后的函数
 */
const debounce = (fn, delay, immediate) => {
  let timer;
  let immediateInvoked = false;

  /**
   * 防抖函数的核心实现
   * 它会取消上一次的定时器并在指定延迟后执行原函数
   * 如果设置了immediate,并且在等待时间内调用,则会在第一次调用时立即执行
   */
  const debounceFn = function (...args) {
    timer && clearTimeout(timer);
    if (immediate && !immediateInvoked) {
      fn.apply(this, args);
      immediateInvoked = true;
    } else {
      timer = setTimeout(() => {
        fn.apply(this, args);
        immediateInvoked = false;
      }, delay);
    }
  };

  /**
   * 取消防抖函数的执行
   * 这个方法允许用户在防抖函数执行之前取消它
   */
  debounceFn.cancel = function () {
    if (timer) {
      clearTimeout(timer);
      timer = null;
      immediateInvoked = false;
    }
  };

  return debounceFn;
};

防抖应用场景

应用场景:搜索框输入、文本输入的自动保存、表单校验、resize事件触发

节流函数(throttle)

节流函数无论用户触发事件多少次,在给定的事件间隔内只会触发一次

封装

/**
 * @param {Function} fn 要节流的函数。
 * @param {number} delay 执行间隔的时间,单位为毫秒。
 * @returns {Function} 返回一个新的节流函数。
 */
const throttle = (fn, delay) => {
  let flag = false;
  return function (...arguments) {
    if (!flag) {
      // 设置标志为true,表示当前函数正在执行中。
      flag = true;
      setTimeout(() => {
        fn.apply(this, arguments);
        // 执行完毕后,重置标志,允许下一次执行。
        flag = false;
      }, delay);
    }
  };
};

节流的应用场景

处理滚动事件

防抖和节流的适用场景

特性节流防抖
实用型保证一定间隔内回调执行一次等待用户输入完成后执行一次
场景需求实时反馈获取最终输入内容
回调频率每隔固定时间触发一次用户停止输入后触发一次
实用型实时搜索建议、输入状态监听提交表单、搜索请求

总结选择

  • 实时性要求高(如实时展示结果):节流更合适
  • 减少无意义操作(如最终触发请求): 防抖更合适