节流与防抖的理解

168 阅读2分钟

节流与防抖的理解

防抖(debounce):

当事件触发后,延迟 n 秒后再执行回调,在延迟的 n 秒时间当中如果重新触发该事件,原先的回调会被取消重新进行计时(与 MOBA 游戏当中角色的回城类似,也就是 "从新开始")。

特点:持续触发不执行、首次触发后,不持续触发的一段时间后执行。

作用: 防抖的作用是在处理输入事件时,避免因用户频繁操作而导致的多次触发事件,从而减少不必要的资源消耗和重复操作,提高页面性能和用户体验。

应用场景

文本输入框搜索:以淘宝搜索框为例,用户输入关键词会触发 onChange 事件请求后端获取与关键词相关的产品,如果用户连续快速地输入关键词就会导致 onChange 事件频繁触发,从而对服务器造成不必要的压力,导致搜索速度变慢,影响用户体验,这种情况就可以利用防抖在规定的时间内限制事件的触发以减少请求次数。

代码示例

  <script>
    var box = document.getElementsByClassName('box')[0];
    
    // 防抖函数
    function debounce(fn, second) {
      let timeOut = null;
      return function() {
        if(timeOut !== null) clearTimeout(timeOut); // 每次执行前需要清除之前的定时器
        timeOut = setTimeout(fn, second); // 延迟执行
      }
    }
    
    // 核心执行函数
    function fn() {
      console.log('触发函数');
    }
​
    box.addEventListener('click', debounce(fn, 1000));
  </script>

节流(throttle):

在规定的时间内只执行一次操作,即当操作触发时,启动一个定时器,在定时器规定的时间当中只执行一次操作,其他操作会被忽略(类似 MOBA 游戏当中英雄角色单位的普通攻击,无论发起普通攻击多少次,单位时间内只执行一次普通攻击,也就是"禁止打断")。

特点:持续触发不会多次执行、到达一定时间间隔后再去执行。

作用:可以减少一段时间内事件的触发频率,节省页面资源。

应用场景

  • 滚动事件:有些页面在滚动时会频繁触发 scroll 事件,执行相应的回调(常见的有 APP 屏幕滑动刷新页面或获取更多数据等,一般会请求接口获取更多数据),使用节流可以避免频繁执行回调函数提高滚动时的性能表现。

  • 视频播放时间记录:像 bilibili 等视频播放网站在播放视频时会记录一下播放时间,以方便没看完的下次可以继续看,这就需要不断触发事件记录视频播放时间,这时候使用节流定时记录可以减少事件的频繁触发,节省页面资源。

  • 还有像快速点击、鼠标滑动、resize 事件等高频事件也可以用使用节流。

代码示例

  <script>
    var box = document.getElementsByClassName('box')[0];
​
    // 节流函数
    function throttle(fn, second) {
      let timeOut = null;
      return function () {
        if (timeOut !== null) return; // 上一次执行没结束前禁止打断
        timeOut = setTimeout(() => {
          fn();
          timeOut = null; // 一次执行完将计时器清空
        }, second);
      }
    }
​
    function fn() {
      console.log('触发函数');
    }
​
    box.addEventListener('click', throttle(fn, 1000));
  </script>

实际开发中可以使用 Lodash 库中的 debounce(防抖)和 throttle(节流)来实现。