美文网首页
防抖节流的实现和防抖函数的封装

防抖节流的实现和防抖函数的封装

作者: Ringo_ | 来源:发表于2022-11-29 16:44 被阅读0次

    防抖

    防抖即“防止抖动”,当我们频繁触发一个事件时,每次事件都会执行,会造成不必要的性能损失。

    防抖就是要延迟执行,在频繁触发事件时,让某个函数只能执行最后一次。

    我们一直触发事件,但是不执行,只有在停止操作一段时间后才执行,就好像电脑的休眠,只有在一段时间内没有使用电脑,电脑才会休眠,如果在这一段时间内使用了电脑,那么电脑就重新开始倒计时。

    下面是一个防抖函数的简单版本:

    let timer: any;
    function debounce(func: Function, delay: number) {
      return function () {
        clearTimeout(timer);
        timer = setTimeout(() => {
          func();
        }, delay);
      };
    }
    

    通过延时函数,在触发事件后,先将之前的setTimeout清除,然后重新定义timer重新计时,如果在delay的时间内,没有重复触发,那么函数顺利执行,如果被重复触发,那就再重新计时。

    但这还没完全结束,在js中,这时在func内部打印this,会发现这样执行的话this指向的是window,所以需要使用apply改变this指向。
    另外要考虑到func接收的参数,不同的函数会有不同的参数传入,对于参数可以使用arguments处理。

    let timer;
    function debounce(fun,delay){
      return function(){
        clearTimeout(timer);
        let args = arguments;
        timer=setTimeout(()=>{
          fun.apply(this,args)
        },delay)
      }
    }
    

    节流

    节流的概念是:在单位时间内,频繁触发事件,只执行一次。

    比如我最近在做的项目:地图组件+时间轴组件,当在时间轴上切换不同的时间点时,会根据时间点,请求该时间点对应的强对流信息png图(降水、雷暴等),然后将图片渲染在地图上,显示该时间点的强对流色斑图。在渲染一张png时,要创建新的色斑图图层,在离开该时间点时,要将该图层销毁,但是这个过程需要时间,于是就出现bug了:在频繁切换时间点的时候,地图报错:在销毁时找不到你说的图层!!

    因为切换太快了,这个图层甚至还没来得及创建,就要被销毁,自然而然产生报错,这时候就需要使用节流,防止一段时间内的多次触发。

      let t1: any = 0;
      function throttle(func: Function, time: number) {
        return function () {
          let t2: any = new Date();
          if (t2 - t1 > time) {
            func();
            t1 = t2;
          }
        };
      }
    

    记录两个时间,t1代表初始时间,t2代表当前时间,如果两个时间差值大于time,就执行func并且将初始时间变更为func最新执行的时间。

    对于防抖和节流一个最主观的判断方法就是:在10s内疯狂点击一个按钮,如果使用了防抖则会只执行一次,使用了节流则会每隔一段时间执行一次,这个时间可以自己来掌控。

    封装防抖函数:

    /**
     * 为目标函数添加防抖
     * @param func 目标函数
     * @param time 防抖时间间隔
     * @param immediately 是否立刻执行
     * @returns 防抖的目标函数
     */
    export function antiShake<T extends (...args: any) => void>(func: T, time = 0, immediately = false): T {
      let handler: any = 0;
      let lock = 0;
      // 立即执行
      if (immediately) {
        return function (...args: any) {
          const now = Date.now();
          if (handler) {
            clearTimeout(handler);
          }
          if (lock < now) {
            func(...args);
            lock = now + time;
          } else {
            handler = setTimeout(() => {
              handler = 0;
              func(...args);
            }, time);
          }
        } as T;
      }
      // 不立刻执行
      else {
        return function (...args: any) {
          if (handler) {
            clearTimeout(handler);
          }
          handler = setTimeout(() => {
            handler = 0;
            func(...args);
          }, time);
        } as T;
      }
    }
    

    相关文章

      网友评论

          本文标题:防抖节流的实现和防抖函数的封装

          本文链接:https://www.haomeiwen.com/subject/sltrfdtx.html