TypeScript---设计模式之单例+发布订阅模式

设计模式之单例+发布订阅模式

/**
 * 定义一个回调函数接口,允许接受任意类型的参数数组
 */
interface Callback<T extends any[] = any[]> {
  (...args: T): void
}

/**
 * 实现一个事件总线类,用于管理事件的订阅和发布
 */
class Eventbus {
  // 存储事件名称与对应回调函数集合的映射
  private events: Record<string, Set<Callback>> = {}
  // 使用单例模式确保只有一个事件总线实例
  private static instance: Eventbus
  // 私有构造函数,防止外部直接创建实例
  private constructor() {}

  /**
   * 获取事件总线的单例实例
   * @returns {Eventbus} 事件总线实例
   */
  static getInstance(): Eventbus {
    return (Eventbus.instance ??= new Eventbus())
  }

  /**
   * 验证事件名称是否为非空字符串
   * @param eventName 事件名称
   * @throws 如果事件名称为空或非字符串,则抛出错误
   */
  private validateEventName(eventName: string): void {
    if (!eventName) {
      throw new Error('事件名称必须是非空字符串')
    }
  }

  /**
   * 订阅指定事件,当事件触发时执行回调函数
   * @param eventName 事件名称
   * @param cb 回调函数,接受与事件相关的参数数组
   */
  on<T extends any[]>(eventName: string, cb: Callback<T>): void {
    this.validateEventName(eventName)
    try {
      ;(this.events[eventName] ??= new Set()).add(cb as Callback)
    } catch (error) {
      console.error(`为事件-"${eventName}"-注册回调时出错:`, error)
    }
  }

  /**
   * 发布指定事件,执行所有订阅了该事件的回调函数
   * @param eventName 事件名称
   * @param args 传递给回调函数的参数数组
   */
  emit<T extends any[]>(eventName: string, ...args: T): void {
    this.validateEventName(eventName)
    const callbacks = this.events[eventName]
    if (callbacks) {
      callbacks.forEach((cb) => {
        try {
          cb(...args)
        } catch (error) {
          console.error(`对事件-"${eventName}"-执行回调时出错:`, error)
        }
      })
    }
  }

  /**
   * 取消订阅指定事件的某个回调函数
   * @param eventName 事件名称
   * @param cb 要取消订阅的回调函数
   */
  off<T extends any[]>(eventName: string, cb: Callback<T>): void {
    this.validateEventName(eventName)
    const callbacks = this.events[eventName]
    if (callbacks && callbacks.has(cb)) {
      callbacks.delete(cb)
      if (callbacks.size === 0) {
        delete this.events[eventName]
      }
    }
  }

  /**
   * 订阅指定事件的一次性回调函数,事件触发后自动取消订阅
   * @param eventName 事件名称
   * @param cb 回调函数,事件触发时执行一次
   */
  once<T extends any[]>(eventName: string, cb: Callback<T>): void {
    this.validateEventName(eventName)
    const handler: Callback<T> = (...args: T) => {
      try {
        cb(...args)
      } catch (error) {
        console.error(`对事件-"${eventName}"-执行一次性回调时出错:`, error)
      } finally {
        this.off(eventName, handler)
      }
    }
    this.on(eventName, handler)
  }
}

// 创建并导出一个事件总线实例,供外部使用
export const eventbus = Eventbus.getInstance()

页面使用

eventbus.on('add', () => {})
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

开发小关

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

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

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

打赏作者

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

抵扣说明:

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

余额充值