防抖与节流实现及多场景运用变形

防抖(debounce)

防抖函数:一个需要频繁触发的函数,在规定时间内,只让最后一次生效,前面的不生效。

防抖(debounce):不管事件触发频率多高,一定在事件触发n秒后才执行,如果你在一个事件触发的 n 秒内又触发了这个事件,就以新的事件的时间为准,n秒后才执行,总之,触发完事件 n 秒内不再触发事件,n秒后再执行。

1.运用场景一

场景:延迟执行函数

对于连续的事件响应我们只需要执行一次回调:

  • 每次 resize/scroll 触发统计事件
  • 百度查询,账号文本输入的验证(连续输入文字后发送 AJAX 请求进行验证,验证最后一次就好)

效果:多次触发都是延迟执行。
实现:

function debounce(event, time) {
      let timer = null;
      return function (...args) {
        clearTimeout(timer);
        timer = setTimeout(() => {
          event.apply(this, args);
        }, time);
      };
    }

效果为:连续点触发,触发多次事件只执行最后一次。

2.运用场景二

场景:有时候我们需要让函数先立即执行一次,再等后面事件触发后等待n秒执行。以后再多次触发时,只执行最后一次。

我们给debounce函数一个flag用于标示是否立即执行。

效果:连续触发事件,一共执行两次:一开始立即执行一次和最后一次。以后再多次触发时,只执行最后一次。
实现:

function debounce(event, time, flag) {
      let timer = null;
      return function (...args) {
        clearTimeout(timer);
        if (flag && !timer) {
          event.apply(this, args);
        }
        timer = setTimeout(() => {
          event.apply(this, args);
        }, time);
      };
    }

3.运用场景三

立即执行一次,例如按钮防抖,防止用户多次点击(下一次调用必须与前一次调用的时间间隔大于wait才会触发)。

用户给interviewMap点star的时候,我们希望用户点第一下的时候就去调用接口,并且成功之后改变star按钮的样子,用户就可以立马得到反馈是否star成功了,这个情况适用立即执行的防抖函数,它总是在第一次调用,并且下一次调用必须与前一次调用的时间间隔大于wait才会触发。

效果:多次触发事件,立即执行一次。
实现:

      function debounce(func, wait, immediate) {
        var timeout;

        return function (...args) {
          if (timeout) {
            clearTimeout(timeout);
          }
          if (immediate) {
            // 如果已经执行过,不再执行
            var callNow = !timeout;
            timeout = setTimeout(function () {
              timeout = null;
            }, wait);
            if (callNow) func.apply(this, args);
          } else {
            timeout = setTimeout(() => func.apply(this, args), wait);
          }
        };
      }

节流

节流(throttle):不管事件触发频率多高,只在单位时间内执行一次。

时间戳实现实现:

效果:第一次事件肯定触发,最后一次不会触发

function throttle(event, time) {
      let pre = 0;
      return function (...args) {
        if (Date.now() - pre > time) {
          pre = Date.now();
          event.apply(this, args);
        }
      }

定时器实现

效果:第一次事件不会触发,最后一次一定触发

function throttle(event, time) {
      let timer = null;
      return function (...args) {
        if (!timer) {
          timer = setTimeout(() => {
            timer = null;
            event.apply(this, args);
          }, time);
        }
      }
    }

结合版

效果:定时器和时间戳的结合版,也相当于节流和防抖的结合版,第一次和最后一次都会触发

function throttle(event, time) {
      let pre = 0;
      let timer = null;
      return function (...args) {
        if (Date.now() - pre > time) {
          clearTimeout(timer);
          timer = null;
          pre = Date.now();
          event.apply(this, args);
        } else if (!timer) {
          timer = setTimeout(() => {
            event.apply(this, args);
          }, time);
        }
      }
    }

猜你喜欢

转载自blog.csdn.net/HZ___ZH/article/details/113685024