防抖(debounce)与节流(throttle)

200 阅读2分钟

代码示例

  • debounce
/**
 * 防抖函数
 * 触发高频事件后n秒内函数只会执行一次,如果n秒内高频事件再次被触发,则重新计算时间
 * @param fn 函数
 * @param delay 延迟时间
 */
export const debounce = (fn: (...args: any) => any, delay: number) => {
  let timer: any = null;
  return (...args: any[]) => {
    if (timer) {
      clearTimeout(timer);
    }
    timer = setTimeout(() => {
      fn.apply(fn, args);
    }, delay);
  };
};

function sayLog() {
  console.log('防抖...');
}

const inpEle = document.getElementById('inp');
inpEle?.addEventListener('input',debounce(sayLog, 500));
  • throttle
/**
 * 节流函数
 * 高频事件触发,但在n秒内只会执行一次,所以节流会稀释函数的执行频率,不允许方法在指定时间内执行超过一次。
 * @param fn 函数
 * @param delay 延迟时间
 */
export const throttle = (fn: (...fnParams: any[]) => any, delay: number) => {
  let canRun = true;
  return function(...args: any[]) {
    if (!canRun) {
      return;
    }
    canRun = false;
    setTimeout(() => {
      fn.apply(this, args);
      canRun = true;
    }, delay);
  };
};

function getPageWideHigh(e) {
  console.log(e.target.innerWidth, e.target.innerHeight);
}
window.addEventListener('resize', throttle(getPageWideHigh, 5000)); // 一旦触发马上执行,忽略执行完毕之前的所有再次触发

应用场景

  • debounce
    • 触发高频事件后n秒内函数只会执行一次,如果n秒内高频事件再次被触发,则重新计算时间,将一个连续的调用归为一个
  • throttle
    • 高频事件触发,但在n秒内只会执行一次,所以节流会稀释函数的执行频率,不允许方法在指定时间内执行超过一次。

应用举例

  • debounce
    • 文本输入框的验证,输入完成之后验证一次即可,不需要每次都发请求验证
    • onresizeonscroll触发的页面统计事件(统计页面宽高,统计页面滚动位置)
  • throttle
    • 图片懒加载,用户下拉,需要监听滚动事件,然后判断是否该显示图片或加载新数据
    • 对用户输入的验证,不想停止输入再进行验证,而是每n秒进行验证