鸿蒙NEXT开发节流、防抖工具类(ArkTs)

复制代码
import { CacheUtil } from './CacheUtil';
import { DateUtil } from './DateUtil';

/**
 * 节流、防抖工具类(用于点击事件,防止按钮被重复点击)
 *
 * @author 鸿蒙布道师
 * @since 2025/04/07
 */
export class ClickUtil {
  private static throttleTimeoutID: number | null = null; // 节流 timeout ID
  private static flag: boolean = false; // 节流标志位,true 表示已进入执行状态
  private static defaultId: string = DateUtil.getTodayTime().toString(); // 防抖默认 ID

  /**
   * 节流:在一定时间内,只触发一次
   *
   * @param func 要执行的回调函数
   * @param wait 延时的时间,默认为 1000 毫秒
   * @param immediate 是否立即执行,默认为 true
   *                  - true: 立即执行第一次调用
   *                  - false: 等待指定时间后执行
   */
  static throttle(func: () => void, wait: number = 1000, immediate: boolean = true): void {
    if (immediate) {
      // 如果未处于节流状态,则立即执行
      if (!ClickUtil.flag) {
        ClickUtil.flag = true;
        typeof func === 'function' && func();
        ClickUtil.throttleTimeoutID = setTimeout(() => {
          ClickUtil.flag = false;
          if (ClickUtil.throttleTimeoutID !== null) {
            clearTimeout(ClickUtil.throttleTimeoutID);
            ClickUtil.throttleTimeoutID = null;
          }
        }, wait);
      }
    } else {
      // 如果未处于节流状态,则等待指定时间后执行
      if (!ClickUtil.flag) {
        ClickUtil.flag = true;
        ClickUtil.throttleTimeoutID = setTimeout(() => {
          ClickUtil.flag = false;
          typeof func === 'function' && func();
          if (ClickUtil.throttleTimeoutID !== null) {
            clearTimeout(ClickUtil.throttleTimeoutID);
            ClickUtil.throttleTimeoutID = null;
          }
        }, wait);
      }
    }
  }

  /**
   * 防抖:一定时间内,只有最后一次操作,再过 wait 毫秒后才执行函数
   *
   * @param func 要执行的函数
   * @param wait 延时的时间,默认为 1000 毫秒
   * @param clickId 设置的点击事件 ID,用于区分多个点击事件,不传则使用默认 ID
   */
  static debounce(func: () => void, wait: number = 1000, clickId: string = ClickUtil.defaultId): void {
    const cacheKey = `ClickUtil_debounce_timeoutID_${clickId}`;
    const cachedTimeoutID = CacheUtil.get<number>(cacheKey); // 获取缓存的 timeout ID

    // 清除之前的定时器
    if (cachedTimeoutID !== undefined && cachedTimeoutID !== null) {
      clearTimeout(cachedTimeoutID);
    }

    // 设置新的定时器
    const timeoutID = setTimeout(() => {
      typeof func === 'function' && func();
      CacheUtil.remove(cacheKey); // 执行后清除缓存
    }, wait);

    // 缓存当前的 timeout ID
    CacheUtil.put<number>(cacheKey, timeoutID);
  }
}

代码如下:
TypeScript 复制代码
import { CacheUtil } from './CacheUtil';
import { DateUtil } from './DateUtil';

/**
 * 节流、防抖工具类(用于点击事件,防止按钮被重复点击)
 *
 * @author 鸿蒙布道师
 * @since 2025/04/07
 */
export class ClickUtil {
  private static throttleTimeoutID: number | null = null; // 节流 timeout ID
  private static flag: boolean = false; // 节流标志位,true 表示已进入执行状态
  private static defaultId: string = DateUtil.getTodayTime().toString(); // 防抖默认 ID

  /**
   * 节流:在一定时间内,只触发一次
   *
   * @param func 要执行的回调函数
   * @param wait 延时的时间,默认为 1000 毫秒
   * @param immediate 是否立即执行,默认为 true
   *                  - true: 立即执行第一次调用
   *                  - false: 等待指定时间后执行
   */
  static throttle(func: () => void, wait: number = 1000, immediate: boolean = true): void {
    if (immediate) {
      // 如果未处于节流状态,则立即执行
      if (!ClickUtil.flag) {
        ClickUtil.flag = true;
        typeof func === 'function' && func();
        ClickUtil.throttleTimeoutID = setTimeout(() => {
          ClickUtil.flag = false;
          if (ClickUtil.throttleTimeoutID !== null) {
            clearTimeout(ClickUtil.throttleTimeoutID);
            ClickUtil.throttleTimeoutID = null;
          }
        }, wait);
      }
    } else {
      // 如果未处于节流状态,则等待指定时间后执行
      if (!ClickUtil.flag) {
        ClickUtil.flag = true;
        ClickUtil.throttleTimeoutID = setTimeout(() => {
          ClickUtil.flag = false;
          typeof func === 'function' && func();
          if (ClickUtil.throttleTimeoutID !== null) {
            clearTimeout(ClickUtil.throttleTimeoutID);
            ClickUtil.throttleTimeoutID = null;
          }
        }, wait);
      }
    }
  }

  /**
   * 防抖:一定时间内,只有最后一次操作,再过 wait 毫秒后才执行函数
   *
   * @param func 要执行的函数
   * @param wait 延时的时间,默认为 1000 毫秒
   * @param clickId 设置的点击事件 ID,用于区分多个点击事件,不传则使用默认 ID
   */
  static debounce(func: () => void, wait: number = 1000, clickId: string = ClickUtil.defaultId): void {
    const cacheKey = `ClickUtil_debounce_timeoutID_${clickId}`;
    const cachedTimeoutID = CacheUtil.get<number>(cacheKey); // 获取缓存的 timeout ID

    // 清除之前的定时器
    if (cachedTimeoutID !== undefined && cachedTimeoutID !== null) {
      clearTimeout(cachedTimeoutID);
    }

    // 设置新的定时器
    const timeoutID = setTimeout(() => {
      typeof func === 'function' && func();
      CacheUtil.remove(cacheKey); // 执行后清除缓存
    }, wait);

    // 缓存当前的 timeout ID
    CacheUtil.put<number>(cacheKey, timeoutID);
  }
}
相关推荐
贾伟康1 小时前
HarmonyOS API 26 DevEco Code 需求到 ArkTS 骨架的提示词分层
harmonyos·arkts·ai coding·deveco code·工程提效
威哥爱编程2 小时前
模拟面试智能体开发实战 02:回答等半分钟,谁还愿意练?把服务端和流式输出搭起来
python·agent·harmonyos
威哥爱编程3 小时前
模拟面试智能体开发实战 01:面试挂了都不知道挂在哪?用 Python 给自己造一个随叫随到的 AI 面试官
python·agent·harmonyos
贾伟康7 小时前
HarmonyOS API 26 HMAF Skill 可解释任务计划与失败回退
harmonyos·arkts·智能体·skill·hmaf
贾伟康7 小时前
HarmonyOS API 26 HMAF 2.0 意图解析的可解释动作图
harmonyos·arkts·智能体·a2a·hmaf
Starry-sky(jing)7 小时前
Vidda ADB 开启:R Pro 65 找不到开发者选项的处理与连接验收
android·adb·远程控制·电视·vidda
雨白8 小时前
从原理到实践:使用 Kotlin KSP 仿写 ButterKnifeLite
android·kotlin
疯华整猫9 小时前
把二十七个 init 从首帧前面搬走:用 Trae 把启动优化钉进 CI
android·性能优化·ai编程
KevinChaos9 小时前
阳台小花园开发手记 03|HarmonyOS 7.0 互动卡片:叶片伸出边框仍与花盆对齐
华为·harmonyos
传奇开心果9 小时前
【探秘 Jetpack Compose 框架深水区】 第8课:rememberSaveable 的边界在哪里?——Bundle、Saver 与什么值得跨进程存活
android·kotlin