防抖和节流

66 阅读3分钟

防抖

“等电梯模式”描述的是防抖(Debouncing)的概念,这种模式意味着在某个动作结束后的固定时间内,如果没有再次触发该动作,才会执行相应的函数。可以类比为按下电梯按钮,如果过程中又有人进来,15秒等待重新计时,直到15秒后开始运送,如果在设定的时间内没有人再次按下按钮,电梯就会开始运行。

防抖函数实现

/**
 * 防抖函数
 * 在一段时间内连续触发事件,只在最后一次触发事件后的指定延迟时间后执行一次函数
 *
 * @param {Function} fn - 需要防抖处理的函数
 * @param {number} delay - 延迟时间,单位为毫秒
 * @returns {Function} 防抖处理后的函数
 */
function debounce(fn, delay) {
  let timeout;
  return function (...args) {
    // 清除之前的定时器
    clearTimeout(timeout);
    // 设置新的定时器
    timeout = setTimeout(() => {
      fn.apply(this, args);
    }, delay);
  };
}

解释

  1. 变量 timeout:用于存储定时器的标识。
  2. 返回函数:每次调用时都会清除之前的定时器并设置一个新的定时器,只有在一定时间内没有新的调用时,原函数才会执行。

示例用法

const searchInput = document.getElementById('searchInput');

const handleSearch = debounce(() => {
  console.log('Search triggered');
}, 300);

searchInput.addEventListener('input', handleSearch);

在这个示例中,handleSearch 只有在输入停止后的300毫秒后才会执行,即使在输入过程中有多次事件触发。

节流

类比分析

  • 地铁模式:地铁列车按固定的时间间隔发车,不会因为乘客数量的变化而改变发车时间。
  • 节流:函数在固定的时间间隔内最多执行一次,不会因为事件触发频率的变化而改变执行频率。

节流实现

/**
 * 节流
 * 连续触发事件但是在n秒中只执行一次函数。节流会稀释函数的执行频率。
 *
 * 单位时间内,操作n次,选中第一次
 *
 * 特点:只执行一次
 * 设置标识位,看能不能触发事件
 *
 */

function throttle(fn, delay) {
  let canRun = true;
  return function () {
    if (!canRun) return;
    canRun = false;
    setTimeout(() => {
      fn.apply(this, arguments);
      canRun = true;
    }, delay);
  };
}

解释

  1. 变量 canRun: 初始值为 true,表示可以执行函数。
  2. 返回函数: 检查 canRun 是否为 true,如果是则执行函数,并将 canRun 设为 false
  3. setTimeout 回调: 在 delay 毫秒后,执行传入的函数 fn,然后将 canRun 设为 true,以便下次可以执行。

示例用法

const handleScroll = throttle(() => {
  console.log('Scroll event handler called');
}, 200);

window.addEventListener('scroll', handleScroll);

在这个示例中,滚动事件的处理函数 handleScroll 会在每200毫秒内最多执行一次,即使滚动事件频繁触发。

区分防抖与节流

  • 防抖(Debouncing) :在连续触发事件结束后的固定时间内只执行一次函数。
  • 节流(Throttling) :在规定的时间间隔内最多执行一次函数。

例如,都设置时间频率为500ms,在2秒时间内,频繁触发函数,节流,每隔 500ms 就执行一次。防抖,则不管调动多少次方法,在2s后,只会执行一次

如下图所示:

a2c81b50-8787-11eb-ab90-d9ae814b240d.png

应用场景

防抖在连续的事件,只需触发一次回调的场景有:

  • 搜索框搜索输入。只需用户最后一次输入完,再发送请求
  • 手机号、邮箱验证输入检测
  • 窗口大小resize。只需窗口调整完成后,计算窗口大小。防止重复渲染。

节流在间隔一段时间执行一次回调的场景有:

  • 滚动加载,加载更多或滚到底部监听
  • 搜索框,搜索联想功能