防抖与节流

作者: narcissus灬 | 来源:发表于2022-02-23 15:16 被阅读0次

防抖与节流

1. 什么是防抖

对于短时间内连续触发的函数,在函数最后一次调用时刻的 wait 毫秒之后执行。如:监听搜索框的连续输入,监听屏幕的滚动事件等。

基本的防抖

const debounce = (fn, wait = 500) => {
  let timeout = null;
  return function () {
    if (timeout) {
      clearTimeout(timeout);
    }
    timeout = setTimeout(() => {
      fn.apply(this, arguments);
    }, wait);
  };
};

进阶的防抖

对于一些按钮事件,为防止用户多次点击,需要立即执行一次,在函数最后一次调用的 wait 毫秒后,再次点击才能执行。添加立即执行参数(immediate = true)

const debounce = (fn, wait = 500, immediate = false) => {
  let timeout;
  return function () {
    if (immediate) {
      if (!timeout) {
        fn.apply(this, arguments);
      } else {
        clearTimeout(timeout);
      }
      timeout = setTimeout(() => {
        timeout = null;
      }, wait);
    } else {
      if (timeout) {
        clearTimeout(timeout);
      }
      timeout = setTimeout(() => {
        timeout = null;
        fn.apply(this, arguments);
      }, wait);
    }
  };
};

最终优化版

/**
 * 防抖函数最终优化版
 * immediate = false: 在函数最后一次调用的 wait 毫秒之后执行
 * immediate = true: 立即执行第一次,在最后一次调用的 wait 毫秒后,可再次点击继续触发
 * @param {function} fn 需要执行的函数
 * @param {number} wait 时间间隔
 * @param {boolean} immediate 是否立即执行
 * @returns function
 */
const debounce = (fn, wait, immediate = false) => {
  let timeout;
  return function () {
    if (timeout) {
      clearTimeout(timeout);
    } else if (immediate) {
      fn.apply(this, arguments);
    }
    timeout = setTimeout(() => {
      if (!immediate) {
        fn.apply(this, arguments);
      }
      timeout = null;
    }, wait);
  };
};

2. 什么是节流

像节流阀一样的函数,当重复调用函数的时候,至少每隔 wait 毫秒调用一次该函数。对于想控制一些触发频率较高的事件有帮助。

const throttle = (fn, wait = 500) => {
  let isRuning = false;
  let timeout = null;
  return function () {
    if (isRuning) {
      return;
    }
    if (timeout) {
      clearTimeout(timeout);
      timeout = null;
    }
    isRuning = true;
    timeout = setTimeout(() => {
      fn.apply(this, arguments);
      isRuning = false;
      timeout = null;
    }, wait);
  };
};
/**
 * 节流函数最终优化版
 * immediate = false: 不会立即执行,每隔 wait 毫秒后执行一次。
 * immediate = true: 立即执行一次,后续每隔 wait 毫秒后执行一次。
 * @param {function} fn 需要执行的函数
 * @param {number} wait 时间间隔
 * @param {boolean} immediate 是否立即执行
 * @returns function
 */
const throttle = (fn, wait = 500, immediate = false) => {
  let isRuning = false;
  let timeout = null;
  return function () {
    if (isRuning) {
      return;
    }
    if (timeout) {
      clearTimeout(timeout);
      timeout = null;
    } else if (immediate) {
      fn.apply(this, arguments);
    }
    isRuning = true;
    timeout = setTimeout(() => {
      fn.apply(this, arguments);
      immediate = false;
      isRuning = false;
      timeout = null;
    }, wait);
  };
};

3. 防抖节流函数合并版本

/**
 * 防抖节流函数合并版本
 * @param {function} fn 需要执行的函数
 * @param {number} wait 时间间隔
 * @param {'debounce' | 'throttle'} type 防抖或节流
 * @param {boolean} immediate 是否立即执行
 * @returns function
 */
const all = (fn, wait, type = "debounce", immediate = false) => {
  let isRuning = false;
  let timeout = null;
  return function () {
    if (isRuning && type === "throttle") {
      return;
    }
    if (timeout) {
      clearTimeout(timeout);
      timeout = null;
    } else if (immediate) {
      fn.apply(this, arguments);
    }
    isRuning = true;
    timeout = setTimeout(() => {
      if (type === "throttle") {
        fn.apply(this, arguments);
        immediate = false;
      } else {
        if (!immediate) {
          fn.apply(this, arguments);
        }
      }
      isRuning = false;
      timeout = null;
    }, wait);
  };
};

相关文章

网友评论

    本文标题:防抖与节流

    本文链接:https://www.haomeiwen.com/subject/fyvolrtx.html