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

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

作者: 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