前端性能优化之--手写节流函数

本文详细介绍了节流函数的实现方法及其应用场景。包括如何指定函数的首次及末次执行、如何取消节流操作、如何通过Promise或回调获取执行结果等高级特性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

节流函数

相对于防抖函数,节流函数可以说是复杂一些。但也不是不能写,就是思维需要更严谨那么一点点。不懂防抖可以去看看我的上一篇文章。本篇主要进行节流函数的实现。可以指定函数第一次是否执行,最后一次是否执行,也可以取消,也可以通过promise拿到函数执行结果,也可以通过回调函数的方式拿到执行结果。

/**
 * 
 * @param {*} fn 需要节流的函数
 * @param {*} interval 间隔时间
 * @param {*} options 参数 
 * { leading: true, 头部(也就是第一次)是否执行 默认执行
 * trailing: true, 尾部(也就是最后一次触发)是否执行 默认执行
 * successCallback: undefined, 成功回调
 * failCallback: undefined 失败回调 可以用来拿到执行结果
 * }
 * @returns 
 */
function throttle(fn, interval, options = { leading: true, trailing: true, successCallback: undefined, failCallback: undefined }) {
  // 上次节流函数执行的时间
  let lastTime = 0;
  // 定时器 最后一次触发事件时需要
  let timer = null;
  const { leading, trailing, successCallback, failCallback } = options;
  function _throttle(event) {
    return new Promise((resolve, reject) => {
      // 获取当前的时间戳
      const nowTime = new Date().getTime();
      // 第一次是否触发的条件 满足条件 则第一次事件发生不触发
      if (lastTime === 0 && leading === false) lastTime = nowTime;
      // 判断当前的执行时间和上次执行时间的时间差 是否满足间隔时间差
      // 也就是计算一下剩余时间 如果小于等于0 则满足可再次执行条件
      const remainTime = interval - (nowTime - lastTime);
      if (remainTime <= 0) {
        // 定时器存在的话 直接取消 因为我现在已经要执行函数了
        if (timer) {
          clearTimeout(timer);
          timer = null;
        }
        // 执行 并可以拿到返回值结果
        try {
          const res = fn.call(this, event);
          if (typeof successCallback === "function") successCallback(res);
          resolve(res);
        } catch (error) {
          if (typeof failCallback === "function") failCallback(error);
          reject(error);
        }
        // 更新上次函数的执行时间
        lastTime = nowTime;
      }
      // 需要执行最后一次
      else if (trailing && !timer) {// 定时器是不需要每次更新的  没什么必要
        timer = setTimeout(() => {
          // 执行函数 也需要清空当前使用了的定时器
          timer = null;
          // TODO 难点:最后一次函数执行时间的重置 第一次如果需要执行,将时间置为当前最新的时间 否则置为0
          lastTime = !leading ? 0 : new Date().getTime();
          // 执行 并可以拿到返回值结果
          try {
            const res = fn.call(this, event);
            if (typeof successCallback === "function") successCallback(res);
            resolve(res);
          } catch (error) {
            if (typeof failCallback === "function") failCallback(error);
            reject(error);
          }
        }, remainTime);
      }
    });
  }
  // 取消功能
  _throttle.cancel = function () {
    if (timer) {
      clearTimeout(timer);
      timer = null;
      lastTime = 0;
    }
  }
  return _throttle;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

尤雨东

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值