JavaScript节流和防抖

127 阅读1分钟

节流throttle

image.png 可以这么比喻,节流就是游戏中技能cd,立即释放后需要等待cd结束才能再次释放 简易版实现如下:

const throttle = (f, time) => {
  let timer = null;
  return (...args) => {
    if (timer) {
      return;
    }
    f.apply(undefined, args);
    timer = setTimeout(() => {
      timer = null;
    }, time);
  };
};

节流的业务常见场景

  • 经常用在用户频繁点击按钮,如每五秒钟点一次抢购
  • drag和scroll期间触发某个回调,要设置一个时间间隔

防抖debounce

image.png 可以这么比喻,防抖就是游戏中回城被打断,需要重新回城等待回城条结束并不被打断才能继续成功回城,简易版代码如下:

const debounce = (f, time) => {
  let timer = null;
  return (...args) => {
    if (timer) {
      clearTimeout(timer); //打断回城
    }
    //重新回城
    timer = setTimeout(() => {
      f.apply(undefined, args);
      timer = null;
    }, time);
  };
};

防抖的业务常见场景

  1. 页面修改大小的时候,重新定位,每次拖动打断,拖动结束停留3秒后就resize
  2. 搜索框打字停止一两秒时候才开始提前搜索关键词

答案

  • 节流:限制执行频率,有节奏的执行
  • 防抖:限制执行次数,多次密集的触发只执行一次
  • 节流关注过程,防抖关注结果

划重点

  • 过程(限制频率) vs 结果
  • 实际工作用lodash loadsh.com/

具体案例演示代码

  • 节流
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <p>throttle 节流</p>
    <div id="div1" draggable="true" style="width: 100px; height: 100px; background-color: aqua; padding: 10px"></div>
    <script>
      function throttle(fn, delay = 200) {
        let timer = null
        return function () {
          if (timer) return
          fn.apply(this, arguments)
          timer = setTimeout(() => {
            timer = null
          }, delay)
        }
      }
      const div1 = document.getElementById('div1')
      div1.addEventListener(
        'drag',
        throttle((e) => {
          console.log('鼠标的位置', e.offsetX, e.offsetY)
        })
      )
    </script>
  </body>
</html>

  • 防抖
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <p>debounce 防抖</p>
    搜索<input id="input1" />
    <script>
      function debounce(fn, delay = 200) {
        let timer = null
        return function () {
          if (timer) clearTimeout(timer)
          timer = setTimeout(() => {
            fn.apply(this, arguments)
            timer = null
          }, delay)
        }
      }
      const input1 = document.getElementById('input1')
      input1.addEventListener(
        'keyup',
        debounce(() => {
          console.log('发起搜索', input1.value)
        }),
        300
      )
    </script>
  </body>
</html>