Skip to content

手动实现防抖节流

防抖:事件被触发 n 秒后再执行回调,如果在这 n 秒内事件又被触发,则重新计时,,防止在短时间内过于频繁的执行相同的任务。当短时间内的频繁是不必要的时候,就可以考虑去抖动,避免资源浪费,或造成不友好的体验。

节流:规定一个单位时间,在这个单位时间内,只能有一次触发事件的回调函数执行,如果在同一个单位时间内某事件被触发多次,只有一次能生效

防抖函数的应用场景:

  • 按钮提交场景:防⽌多次提交按钮,只执⾏最后提交的⼀次
  • 服务端验证场景:表单验证需要服务端配合,只执⾏⼀段连续的输⼊事件的最后⼀次,还有搜索联想词功能类似⽣存环境请⽤lodash.debounce

节流函数的适⽤场景:

  • 拖拽场景:固定时间内只执⾏⼀次,防⽌超⾼频次触发位置变动
  • 缩放场景:监控浏览器resize
  • 动画场景:避免短时间内多次触发动画引起性能问题
js
/**
 * debounce 防抖
 * @param fn [function] 需要防抖的函数
 * @param delay [number] 毫秒,防抖期限值
 */
function debounce(fn, delay) {
  let timer = null; //借助闭包
  return function (...arg) {
    if (timer) {
      //进入该分支语句,说明当前正在一个计时过程中,并且又触发了相同事件。
      // 所以要取消当前的计时,重新开始计时
      clearTimeout(timer);
    }
    timer = setTimeout(() => {
      fn.apply(this, arg); // 使用apply将fn函数的this指向修改为return后的function
    }, delay); // 进入该分支说明当前并没有在计时,那么就开始一个计时
  };
}
js
/**
 * throttle 节流
 * @param fn [function] 需要节流的函数
 * @param delay [number] 毫秒
 */
function throttle(fn, delay) {
  let valid = false; // 节流阀
  return function (...arg) {
    if (valid) {
      //休息时间 暂不接客
      return;
    }
    // 工作时间,执行函数并且在间隔期内把状态位设为无效
    valid = true;
    setTimeout(() => {
      fn.apply(this, arg);
      valid = false;
    }, delay);
  };
}

如有转载或 CV 的请标注本站原文地址