ts节流与防抖的封装

1,188 阅读2分钟

什么是防抖节流

函数防抖 是指在一定时间内,在动作被连续频繁触发的情况下,动作只会被执行一次,也就是说当调用动作过n毫秒后,才会执行该动作,若在这n毫秒内又调用此动作则将重新计算执行时间,所以短时间内的连续动作永远只会触发一次。

函数节流 对于短时间内大量触发同一事件(滚动事件、输入框实时搜索),那么在函数执行一次之后,该函数在指定的时间期限内不再工作,直至过了这段时间才重新生效

函数节流(throttle)函数防抖(debounce) 都是为了限制函数的执行频次,以优化函数触发频率过高导致的响应速度跟不上触发频率,出现延迟,假死或卡顿的现象。

简单记忆 :前节流,后防抖

前节流: 同一个函数,第一次触发执行后开始算时间(自己定义的间隔时长),间隔时间结束前不会在执行这个函数

节流是将多次执行变为每隔一段时间执行一次

后防抖: 同一个函数,第一次触发后开始算时间(自己定义的间隔时长),间隔时间内如果再次触发则重新计算剩余时间,直到最后一次触发的间隔时间计算结束后,才第一次执行这个函数

防抖是将多次执行变成最后一次执行

使用场景

防抖

  • 短信验证码
  • 滚动事件
  • 表单重复提交
  • 页面 resize 事件
  • input 事件(当然也可以用节流,实现输入框实时搜索)

节流

  • scroll 事件,单位时间后计算一次滚动位置
  • input 事件
  • 播放事件,计算进度条

函数封装

节流

// 节流 定时器 + 时间戳
export let throttle = (func: any, delay: number = 200) => {
  // 第一次触发时间戳
  let startTime = Date.now();
  return (...args: any[]) => {
    // 如果不是剪头函数可以使用arguments获取参数,这样就不用写形参了考虑形参个数了
    // let args = arguments;
    // 再次触发时间
    let curTime = Date.now();
    // 间隔时间 = 延迟的时间 - (再次触发时间戳 - 第一次触发时间戳)
    let interval = delay - (curTime - startTime);
    if (interval <= 0) {
      // 重新计算开始时间
      startTime = Date.now();
      return func(...args);
    }
  };
};

防抖

// 防抖
export let debounce = (fn: Function, delay: number = 200) => {
  let timer: any;
  // 闭包
  return (...args: any[]) => {
    // 如果不是剪头函数可以使用arguments获取参数,这样就不用写形参了考虑形参个数了
    // let args = arguments;
    // 判断还在定时,说明当前正在一个计时过程中,并且又触发了相同事件。所以要取消当前的计时,重新开始计时
    if (timer) {
      clearTimeout(timer);
    }
    timer = setTimeout(() => {
      timer = null;
      return fn(...args);
    }, delay);
  };
};