JS限流与防抖

限流

在JS中,如果一个事件频繁触发(比如用户疯狂点击按钮)并且处理函数处理耗时还比较长,那么就容易造成性能问题。

限流函数是针对这类问题的优化方式之一,它要求两次事件处理必须大于某个间隔时间,简而言之就是加了一层判断。

限流函数(throttle:节流阀)的核心在于内部维护了一个“上次执行时间点”,通过比较当前执行时间与上次执行时间的差值判断是否“频繁”,是否执行。限流函数本身是一个装饰函数,修饰了事件处理器之后返回一个新的闭包函数。经过限流函数处理之后,事件触发的频率就被限制为预先传入的interval之上了。

下面用代码实现一个限流函数:

function throttle(fn, interval) {
  // 维护上次执行的时间
  let last = 0;

  return function () {
    const context = this;
    const args = arguments;
    const now = Date.now();
    // 根据当前时间和上次执行时间的差值判断是否频繁
    if (now - last >= interval) {
      last = now;
      fn.apply(context, args);
    }
  };
}

使用限流函数:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta
      name="viewport"
      content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"
    />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title>Document</title>
  </head>
  <body>
    <button>click me</button>
    <script src="./throttle.js"></script>
    <script>
      const button = document.querySelector("button");
      button.addEventListener(
        "click",
        // 使用限流函数修饰事件处理器
        throttle((event) => {
          console.log("button click");
        }, 2000)
      );
    </script>
  </body>
</html>

防抖

防抖函数也是一种限流函数,但要特殊一些。最典型的场景是表单输入,如果我们要在表单中监听input事件(比如远程搜索),那用户在输入的时候也会频繁触发,但这里使用throttle函数不行,因为我们需要等待用户停止输入一段时间后才能确认用户输入的值,所以要定义一个新的限流函数,叫做防抖函数。

防抖(防反跳)函数的核心是内部使用定时器并维护定时器返回的ID值,如果持续触发则不断clearTimeout()并重新发起setTimeout(),通过这种方式等待事件触发完毕,然后进行延时处理。

下面用代码实现一个防抖函数:

function debounce(fn, delay) {
  // 记录定时器返回的ID
  let timer = null;

  return function () {
    const context = this;
    const args = arguments;
    // 当有事件触发时清除上一个定时任务
    if (timer) {
      clearTimeout(timer);
    }
    // 重新发起一个定时任务
    timer = setTimeout(() => {
      fn.apply(context, args);
    }, delay);
  };
}

使用防抖函数:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta
      name="viewport"
      content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"
    />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title>Document</title>
  </head>
  <body>
    <input type="text" />
    <script src="debounce.js"></script>
    <script>
      const input = document.querySelector("input");
      input.addEventListener(
        "input",
        debounce((event) => {
          console.log("input finish");
        }, 2000)
      );
    </script>
  </body>
</html>

这些常用的函数可以参考lodash库

总结

限流函数和防抖函数都是为了应对“事件处理的速度跟不上事件触发的速度”这样的场景而产生的优化函数。

限流(throttle)要求两次事件处理之间必须有一个间隔时间,防抖(debounce)要求最后一个事件触发完毕后再执行。

posted @ 2020-07-06 13:02  Peterer~王勇  阅读(2419)  评论(0编辑  收藏  举报