函数的防抖与节流

485 阅读2分钟

防抖和节流的区别

  • 防抖:在一定间隔内疯狂触发函数的情况下,函数只执行一次。(至于是一触发,就执行,还是疯狂触发的最后一次执行可以自己控制,一般为了防止延迟,都是选择第一次触发就执行。)假如,我们设定的间隔是500ms,那么在触发间隔小于500ms的都算是疯狂触发函数,只会执行一次。当触发间隔大于500ms后,就会重新计算执行函数。

    应用场景:按钮点击

  • 节流:在连续触发函数的一定时间内,根据设置的时间间隔,每过一个时间间隔触发一次函数就是节流。例如,我疯狂触发了一个函数持续1min,设置的时间间隔是500ms,那么这个函数在这1min内,每隔500ms就会执行一次。

    应用场景:页面滚动,拖拽

防抖代码实现

参数:

  • funcFunction,代表要执行的函数(业务)
  • waitNumber , 代表连续触发的最大时间间隔,默认值500ms
  • immediateBoolean,是否一触发就执行,默认值是false
  1. 定时器方式
function debounce(func, wait=500, immediate=false) {
  let timer = null;
  return function proxy(...params) {
    let self = this;
    if (immediate) {
      !timer ? func.call(self, ...params) : null;
      clearTimeout(timer);
      timer = setTimeout(() => {
        timer = null;
      }, wait);
    } else {
      clearTimeout(timer);
      timer = setTimeout(() => {
        timer = null;
        func.call(self, ...params);
      }, wait);
    }
  };
}
  1. 时间戳
function debounce(func, wait=500, immediate=false) {
    let now = 0;
    let timer = null;
    return function proxy(...params) {
      let thenow = Date.now();
      if (immediate) {
        thenow - now >= wait ? func.call(this, ...params) : null;
        now = thenow;
      } else {
        clearTimeout(timer);
        timer = setTimeout(() => {
          timer = null;
          func.call(this, ...params);
        }, wait);
      }
    };
}

我发现好像利用时间戳的方式没有办法实现后执行,只能实现先执行的这种情况。

节流代码实现

function throttle(func, wait, immediate) {
  let now = 0;
  let timer = null;
  return function proxy(...params) {
    let thenow = Date.now();
    let waiting = wait - (thenow - now);
    if (immediate) {
      if (waiting <= 0) {
        func.call(this, ...params);
        now = thenow;
      } else {
        if (!timer) {
          timer = setTimeout(() => {
            func.call(this, ...params);
            now = Date.now();
            timer = null;
          }, waiting);
        }
      }
    } else {
      if (!timer) {
        timer = setTimeout(
          () => {
            func.call(this, ...params);
            now = Date.now();
            timer = null;
          },
          waiting >= 0 ? waiting : wait
        );
      }
    }
  };
}

虽然上面写了立即执行和延迟执行两种,但是一般不会选择延迟执行这种方式