节流与防抖


是什么?

本质上使用中优化高频率执行代码的一种手段
浏览器的 resizescrollkeypressmousemove 等事件在触发时,会高频率的调用绑在事件上的回调函数,极大浪费了资源,降低前端的性能。
对此我们采用节流、防抖来降低事件触发的频率

定义

  • 节流: n 秒内只运行一次,若在 n 秒内重复触发,只有一次生效

  • 防抖: n 秒后在执行该事件,若在 n 秒内被重复触发,则重新计时

节流

<body>
    <button onclick="myclick()">按钮</button>
    <button onclick="myclick2()">定时器写法按钮</button>
</body>
<script>
    // 时间戳写法
    function throttled1(fn, delay = 500){
       let startTime=Date.now();
       return function(...args){
          const nowTime=Date.now();
          console.log(nowTime-startTime,delay)
          if(nowTime-startTime>=delay){
             fn.apply(null,args);
             startTime=Date.now();
          }
       }
    }
    const myclick=throttled1(()=>{
        console.log("事件执行一次");
    })
    
    // 定时器的写法
    function throttled2(fn, delay = 500) {
      let timer = null;
      return function (...args) {
        if (!timer) {
          timer = setTimeout(() => {
            fn.apply(this, args);
            timer = null;
          }, delay);
        }
      };
    }

    const myclick2=throttled2(()=>{
        console.log("执行事件一次");
    })

  
</script>

防抖

<script>
     function debounce(fn, wait) {
      var timer = null;
      return function () {
        if (timer !== null) {
          clearTimeout(timer);
        }
        timer = setTimeout(fn, wait);
      };
    }

    function handle() {
      console.log(Math.random());
    }

    window.addEventListener("resize", debounce(handle, 1000));
</script>

应用场合:

  1. 搜索框搜索输入。只需用户最后一次输入完,再发送请求;
  2. 用户名、手机号、邮箱输入验证;
  3. 浏览器窗口大小改变后,只需窗口调整完后,再执行 resize 事件中的代码,防止重复渲染。

加强版本的示例

function debounce(func, wait, immediate) {
      let timer;

      return function () {
        let context = this;
        let args = arguments;
        if (timer) {
          clearTimeout(timer);
        };

        if (immediate) {
          var callNow = !timer;
          timer = setTimeout(() => {
            timer = null;
          }, wait);
          // 为空执行
          if (callNow){
            func.apply(context, args)
          }
        } else {
          timer = setTimeout(function () {
            func.apply(context, args);
          }, wait);
        }
      };
    }

    function handle() {
      console.log(Math.random());
    }

    window.addEventListener("resize",debounce(handle,1000,true)); // 调用立即执行版本
    // window.addEventListener("mousemove", debounce(handle, 1000, false)); // 调用非立即执行版本

文章作者: ycs
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 ycs !
  目录