TypeScript 中的事件总线与观察者模式:实现与示例

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

TypeScript 中的事件总线与观察者模式



观察者模式(Observer)及其实际实现——事件总线(Event Bus)——是构建低耦合、可扩展应用程序的基础工具。在本文中,我们将详细讲解如何在 TypeScript 中使用强类型实现事件总线,并探讨其在教育项目中的应用。



什么是观察者模式?

观察者模式定义了对象之间的一对多关系。当一个对象(发布者,subject)改变其状态时,所有依赖它的对象(观察者,observers)都会自动收到通知并更新。这可以避免组件之间的紧密耦合。



什么是事件总线?

事件总线(Event Bus)是一种实现观察者模式的集中式机制。组件不直接让观察者订阅发布者,而是通过一个统一的总线进行通信。组件可以:

  • 订阅(subscribe/listen)特定事件。
  • 发布(emit/publish)事件,该事件将传递给所有订阅者。
  • 取消订阅(unsubscribe)事件,当不再需要时。

这种方法非常适合:

  • 互不知晓的模块之间的交互。
  • 处理用户操作(点击、数据输入)。
  • 响应应用程序状态的变化(数据加载、错误)。


在 TypeScript 中实现事件总线

TypeScript 添加了强大的类型系统,使事件总线更安全、更可预测。我们将创建一个类型化的事件总线,其中每个事件都有严格定义的参数集。



1. 定义事件类型

首先,为事件名称及其参数定义一个映射接口:

// 定义事件映射:键是事件名称,值是参数类型interface EventMap {    'user:login': { userId: string; timestamp: number };    'data:loaded': { items: string[] };    'error:occurred': { message: string; code: number };    // 可以添加任何其他事件}


2. 创建 EventBus 类

现在,使用泛型创建类本身,以实现强类型:

type Listener<T> = (payload: T) => void;

class EventBus<T extends Record<string, unknown>> { private listeners: Map<keyof T, Set<Listener<unknown>>> = new Map();

// 订阅事件 subscribe<K extends keyof T>(event: K, listener: Listener<T[K]>): () => void { if (!this.listeners.has(event)) { this.listeners.set(event, new Set()); } const currentListeners = this.listeners.get(event)!; currentListeners.add(listener as Listener<unknown>);

// 返回取消订阅的函数 return () => { currentListeners.delete(listener as Listener<unknown>); }; }

// 发布事件 emit<K extends keyof T>(event: K, payload: T[K]): void { const currentListeners = this.listeners.get(event); if (currentListeners) { currentListeners.forEach((listener) => { listener(payload); }); } }

// 取消所有订阅(用于清理) clear(): void { this.listeners.clear(); }}

// 使用我们的事件映射创建总线实例export const appEventBus = new EventBus<EventMap>();


3. 使用示例

让我们看看不同模块如何通过事件总线进行交互:



// 认证模块class AuthService {    login(userId: string) {        // ... 登录逻辑 ...        appEventBus.emit('use                    

推荐