Skip to content

@utilslib/core/StateStore

StateStore

函数签名

typescript
function StateStore() { ... }
点击查看源码
js
/**
 * 确保传入的方法只能被执行一次
 *
 * @param {(...args: any) => any} func - 要执行的方法。
 * @returns {(...args: any) => any} 返回一个新的方法,该方法只会执行一次
 */
function once(fn) {
  // 利用闭包判断函数是否执行过
  let called = false;
  return function (...args) {
    if (!called) {
      called = true;
      return fn.apply(this, args);
    }
  };
}
/**
 * 一个简单的事件发射器类,用于实现发布-订阅模式
 */
export class EventEmitter {
  /** 存储所有事件及其对应的监听函数 */
  events;
  constructor() {
    this.events = new Map();
  }
  /**
   * 为指定事件添加监听器
   * @param {string} eventName - 要监听的事件名称
   * @param {Function} callback - 事件触发时要调用的回调函数
   * @returns {Function} 返回一个用于取消订阅的函数
   */
  on(eventName, callback) {
    const callbacks = this.events.get(eventName) ?? [];
    this.events.set(eventName, [...callbacks, callback]);
    return () => once(this.off.bind(this))(eventName, callback);
  }
  /**
   * 为指定事件添加一次性监听器,触发后自动移除
   * @param {string} eventName - 要监听的事件名称
   * @param {Function} callback - 事件触发时要调用的回调函数
   * @returns {Function} 返回一个用于取消订阅的函数
   */
  once(eventName, callback) {
    const wrapper = (...args) => {
      callback(...args);
      this.off(eventName, wrapper);
    };
    return this.on(eventName, wrapper);
  }
  /**
   * 移除指定事件的特定监听器
   * @param {string} eventName - 事件名称
   * @param {Function} callback - 要移除的监听器函数
   */
  off(eventName, callback) {
    const callbacks = this.events.get(eventName);
    if (!callbacks) return;
    const index = callbacks.indexOf(callback);
    index !== -1 && callbacks.splice(index, 1);
    callbacks.length === 0 && this.events.delete(eventName);
  }
  /**
   * 移除指定事件的所有监听器,如果没有指定事件名称则移除所有事件的监听器
   * @param {string} [eventName] - 可选的事件名称
   */
  removeAllListeners(eventName) {
    if (eventName) {
      this.events.delete(eventName);
    } else {
      this.events.clear();
    }
  }
  /**
   * 触发指定事件,调用所有监听该事件的回调函数
   * @param {string} eventName - 要触发的事件名称
   * @param {...any} args - 传递给监听器的参数
   */
  emit(eventName, ...args) {
    const callbacks = this.events.get(eventName);
    if (!callbacks) return;
    // 创建回调函数数组的副本,防止回调函数中的操作影响遍历
    const callbacksCopy = [...callbacks];
    callbacksCopy.forEach((callback) => {
      try {
        callback(...args);
      } catch (error) {
        console.error(`Error in event handler for ${eventName}:`, error);
      }
    });
  }
}
/*
 * 状态管理存储类
 * 用于管理应用状态并提供发布订阅功能
 */
export class StateStore {
  state;
  eventEmitter;
  constructor() {
    this.state = {};
    this.eventEmitter = new EventEmitter();
  }
  /**
   * 设置状态
   * @param {keyof T} key - 状态键名
   * @param {T[keyof T]} value - 状态值
   */
  set(key, value) {
    this.state[key] = value;
    this.eventEmitter.emit(key, value);
  }
  /**
   * 获取状态
   * @param {keyof T | undefined} key - 状态键名,不传则返回整个状态对象
   * @returns {T[keyof T] | T} 对应键的状态值或整个状态对象
   */
  get(key) {
    return key ? this.state[key] : this.state;
  }
  /**
   * 订阅状态变化
   * @param {keyof T} key - 要订阅的状态键名
   * @param {(value: T[keyof T]) => void} callback - 状态变化时的回调函数
   * @returns {() => void} 取消订阅的函数
   */
  subscribe(key, callback) {
    return this.eventEmitter.on(key, callback);
  }
  /**
   * 取消订阅
   * @param {keyof T} key - 要取消订阅的状态键名
   * @param {(value: T[keyof T]) => void} callback - 之前注册的回调函数
   */
  unsubscribe(key, callback) {
    this.eventEmitter.off(key, callback);
  }
  /**
   * 通知所有监听者
   * @param {keyof T} key - 要通知的状态键名
   * @param {T[keyof T]} value - 要传递的值
   */
  notify(key, value) {
    this.eventEmitter.emit(key, value);
  }
  /**
   * 清空状态
   */
  clear() {
    this.state = {};
    this.eventEmitter.removeAllListeners();
  }
}
ts
export type AnyFunction = (...args: any) => any;

/**
 * 确保传入的方法只能被执行一次
 *
 * @param {(...args: any) => any} func - 要执行的方法。
 * @returns {(...args: any) => any} 返回一个新的方法,该方法只会执行一次
 */
function once<F extends AnyFunction>(fn: F) {
  // 利用闭包判断函数是否执行过
  let called = false;
  return function (this: unknown, ...args: Parameters<F>) {
    if (!called) {
      called = true;
      return fn.apply(this, args);
    }
  };
}

/**
 * 一个简单的事件发射器类,用于实现发布-订阅模式
 */
export class EventEmitter<T extends string> {
  /** 存储所有事件及其对应的监听函数 */
  private events: Map<T, AnyFunction[]>;

  constructor() {
    this.events = new Map();
  }

  /**
   * 为指定事件添加监听器
   * @param {string} eventName - 要监听的事件名称
   * @param {Function} callback - 事件触发时要调用的回调函数
   * @returns {Function} 返回一个用于取消订阅的函数
   */
  on(eventName: T, callback: AnyFunction): () => void {
    const callbacks = this.events.get(eventName) ?? [];
    this.events.set(eventName, [...callbacks, callback]);
    return () => once(this.off.bind(this))(eventName, callback);
  }

  /**
   * 为指定事件添加一次性监听器,触发后自动移除
   * @param {string} eventName - 要监听的事件名称
   * @param {Function} callback - 事件触发时要调用的回调函数
   * @returns {Function} 返回一个用于取消订阅的函数
   */
  once(eventName: T, callback: AnyFunction): () => void {
    const wrapper = (...args: any[]) => {
      callback(...args);
      this.off(eventName, wrapper);
    };
    return this.on(eventName, wrapper);
  }

  /**
   * 移除指定事件的特定监听器
   * @param {string} eventName - 事件名称
   * @param {Function} callback - 要移除的监听器函数
   */
  off(eventName: T, callback: AnyFunction): void {
    const callbacks = this.events.get(eventName);
    if (!callbacks) return;
    const index = callbacks.indexOf(callback);
    index !== -1 && callbacks.splice(index, 1);
    callbacks.length === 0 && this.events.delete(eventName);
  }

  /**
   * 移除指定事件的所有监听器,如果没有指定事件名称则移除所有事件的监听器
   * @param {string} [eventName] - 可选的事件名称
   */
  removeAllListeners(eventName?: T): void {
    if (eventName) {
      this.events.delete(eventName);
    } else {
      this.events.clear();
    }
  }

  /**
   * 触发指定事件,调用所有监听该事件的回调函数
   * @param {string} eventName - 要触发的事件名称
   * @param {...any} args - 传递给监听器的参数
   */
  emit(eventName: T, ...args: any[]): void {
    const callbacks = this.events.get(eventName);
    if (!callbacks) return;

    // 创建回调函数数组的副本,防止回调函数中的操作影响遍历
    const callbacksCopy = [...callbacks];

    callbacksCopy.forEach((callback) => {
      try {
        callback(...args);
      } catch (error) {
        console.error(`Error in event handler for ${eventName}:`, error);
      }
    });
  }
}

/*
 * 状态管理存储类
 * 用于管理应用状态并提供发布订阅功能
 */
export class StateStore<T extends Record<string, any> = Record<string, any>> {
  private state: T;
  private eventEmitter: EventEmitter<string>;

  constructor() {
    this.state = {} as T;
    this.eventEmitter = new EventEmitter<string>();
  }

  /**
   * 设置状态
   * @param {keyof T} key - 状态键名
   * @param {T[keyof T]} value - 状态值
   */
  set<K extends keyof T>(key: K, value: T[K]): void {
    this.state[key] = value;
    this.eventEmitter.emit(key as string, value);
  }

  /**
   * 获取状态
   * @param {keyof T | undefined} key - 状态键名,不传则返回整个状态对象
   * @returns {T[keyof T] | T} 对应键的状态值或整个状态对象
   */
  get<K extends keyof T>(key?: K): T[K] | T {
    return key ? this.state[key] : this.state;
  }

  /**
   * 订阅状态变化
   * @param {keyof T} key - 要订阅的状态键名
   * @param {(value: T[keyof T]) => void} callback - 状态变化时的回调函数
   * @returns {() => void} 取消订阅的函数
   */
  subscribe<K extends keyof T>(
    key: K,
    callback: (value: T[K]) => void,
  ): () => void {
    return this.eventEmitter.on(key as string, callback);
  }

  /**
   * 取消订阅
   * @param {keyof T} key - 要取消订阅的状态键名
   * @param {(value: T[keyof T]) => void} callback - 之前注册的回调函数
   */
  unsubscribe<K extends keyof T>(
    key: K,
    callback: (value: T[K]) => void,
  ): void {
    this.eventEmitter.off(key as string, callback);
  }

  /**
   * 通知所有监听者
   * @param {keyof T} key - 要通知的状态键名
   * @param {T[keyof T]} value - 要传递的值
   */
  notify<K extends keyof T>(key: K, value: T[K]): void {
    this.eventEmitter.emit(key as string, value);
  }

  /**
   * 清空状态
   */
  clear(): void {
    this.state = {} as T;
    this.eventEmitter.removeAllListeners();
  }
}

如有错误,请提交issue :::