实现节流函数

37 阅读1分钟

什么是节流

如果持续触发事件,每隔一段时间只会会执行一次。

应用场景

DOM 元素拖拽
监听 scroll 滚动事件
计算鼠标移动的距离

一些知识点

const nowTime = new Date().valueOf(); // 获取当前时间戳

使用时间戳实现

const jieliu(fn, wait) {
    let old = 0;
    return function() {
        const _this = this;
        const args = arguments;
        let now = new Date().valueOf();
        if (now - old > wait) {
            fn.apply(_this, args);
            old = now;
        }
    }
}

使用定时器实现

function throttle(fn, wait) {
    let flag = true;
    return function() {
        if (!flag) return;
        const args = arguments;
        flag = false;
        setTimeout(() => {
            fn.apply(this, args);
            flag = true;
        }, wait);
    }
}
function throttle(fn, wait) {
    let timer;
    return function () {
        if (timer) return;
        const args = arguments;
        timer = setTimeout(() => {
            timer = null;
            fn.apply(this, args);
        }, wait);
    };
}

使用时间戳和定时器结合实现

function throttle(fn, await, option = {}) {
  let old = 0;
  let timer;
  return function () {
    const _this = this;
    const args = arguments;
    let now = new Date().valueOf();

    // 第一次触发立即执行
    if (now - old > await && option.leading === true) {
      if (timer) {
        clearTimeout(timer);
        timer = null;
      } else {
        fn.apply(_this, args);
        old = now;
      }
    }

    // 最后一次会触发
    if (!timer && option.trailing === true) {
      timer = setTimeout(() => {
        timer = null;
        old = new Date().valueOf();
        fn.apply(_this, args);
      }, await);
    }
  };
}

验证

<div id="box" style="background-color: #ccc; width: 500px; height: 500px;"></div>
const boxEle = document.getElementById('box');
function handler() {
    console.log('123');
}
boxEle.addEventListener(
  "mousemove",
  throttle(handler, 3000, { leading: false, trailing: true })
);

总结

使用时间戳实现节流,第一次立即触发,最后一次不触发;

使用定时器实现节流,第一次不会立即触发,会在规定时间后触发,因为第一次执行就会开启定时器,最后一次会触发;

使用时间戳和定时器结合实现,第一次会立即触发,最后一次离开也会触发。