debounce & throttle

60 阅读1分钟

debounce

const debounce = (func, delay) => {
  let timer = null;
  let lastArgs;
  let lastCtx;
  return function (...args) {
    lastCtx = this;
    lastArgs = args;
    if (timer) {
      clearTimeout(timer);
    }
    timer = setTimeout(function () {
      func.apply(lastCtx, lastArgs);
      timer = null;
    }, delay);
  };
};

const f1 = () => console.log(123);
const deF1 = debounce(f1, 1000);

deF1();
setTimeout(() => deF1(), 200);
setTimeout(() => deF1(), 500);
setTimeout(() => deF1(), 1600);
setTimeout(() => deF1(), 2000);
// 预期只输出两次123

throttle

第一版 默认leading trailing都为true 简化实现

const throttle = (func, delay, options) => {
  const { trailing = true, leading = true } = options || {};
  let lastCtx;
  let lastArgs;
  let previous = 0;
  let timer;
  // 默认trailing leading都为true的一版代码
  return function (...args) {
    lastCtx = this;
    lastArgs = args;
    const now = Date.now();
    // if (!previous) previous = now;
    if (now - previous > delay) {
      // 可以立即执行
      if (timer) {
        clearTimeout(timer);
        timer = null;
      }
      func.apply(lastCtx, lastArgs);
      previous = now;
    } else if (!timer) {
      timer = setTimeout(function () {
        const now = Date.now();
        func.apply(lastCtx, lastArgs);
        previous = now;
        timer = null;
      }, previous + delay - now);
    }
  };
};

const f1 = (a) => {
  console.log(a);
};

const throF1 = throttle(f1, 1000, { leading: true, trailing: true });

throF1(0);
setTimeout(() => {
  throF1(111);
}, 500);
setTimeout(() => {
  throF1(222);
}, 600);
setTimeout(() => {
  throF1(333);
}, 700);
// 先输出0 再输出333

const throttle = (func, delay, options) => {
  const { trailing = true, leading = true } = options || {};
  let lastCtx;
  let lastArgs;
  let previous = 0;
  let timer;
  // 默认trailing leading都为true的一版代码
  return function (...args) {
    lastCtx = this;
    lastArgs = args;
    const now = Date.now();
    if (!previous && !leading) previous = now; // 关键改动
    if (now - previous > delay && leading) {
      // 可以立即执行
      if (timer) {
        clearTimeout(timer);
        timer = null;
      }
      func.apply(lastCtx, lastArgs);
      previous = now;
    } else if (!timer && trailing) {
      timer = setTimeout(function () {
        const now = Date.now();
        func.apply(lastCtx, lastArgs);
        previous = leading ? now : 0; // 关键改动
        timer = null;
      }, previous + delay - now);
    }
  };
};

const f1 = (a) => {
  console.log(a);
};

const throF1 = throttle(f1, 1000, { leading: true, trailing: false });

throF1(0);
setTimeout(() => {
  throF1(111);
}, 500);
setTimeout(() => {
  throF1(222);
}, 600);
setTimeout(() => {
  throF1(333);
}, 700);
// 输出0

const throF1 = throttle(f1, 1000, { leading: false, trailing: true });

throF1(0);
setTimeout(() => {
  throF1(111);
}, 500);
setTimeout(() => {
  throF1(222);
}, 600);
setTimeout(() => {
  throF1(333);
}, 700);
// 输出333