TypeScript 中的事件总线与观察者模式:从理论到实践
现代 Web 开发需要灵活且可扩展的架构。有助于组织组件间交互的两个关键模式是 事件总线 和 观察者模式。在本文中,我们将分析它们在 TypeScript 中的实现、优势以及实际使用场景。
什么是观察者模式?
观察者模式 是一种行为设计模式,它定义了对象之间一对多的依赖关系。当一个对象(发布者)改变其状态时,所有依赖对象(订阅者)都会自动收到通知并更新。
该模式的主要元素:
- Subject(发布者) — 跟踪变化并通知订阅者的对象。
- Observer(观察者) — 订阅发布者变化的对象。
- Event Bus(事件总线) — 管理组件间订阅和事件发送的集中式机制。
在 TypeScript 中实现事件总线
TypeScript 为严格类型化提供了出色的支持,这使得事件总线的实现既安全又可预测。让我们来看一个基本实现:
type EventHandler<T = any> = (payload: T) => void;
class EventBus { private listeners: Map<string, EventHandler[]> = new Map();
// 订阅事件 subscribe<T>(event: string, handler: EventHandler<T>): void { if (!this.listeners.has(event)) { this.listeners.set(event, []); } this.listeners.get(event)!.push(handler); }
// 取消订阅事件 unsubscribe<T>(event: string, handler: EventHandler<T>): void { const handlers = this.listeners.get(event); if (handlers) { this.listeners.set( event, handlers.filter(h => h !== handler) ); } }
// 发布事件 emit<T>(event: string, payload: T): void { const handlers = this.listeners.get(event); if (handlers) { handlers.forEach(handler => handler(payload)); } }
// 清除所有订阅 clear(): void { this.listeners.clear(); }}
export const eventBus = new EventBus();使用类型化事件的示例
为了提高类型安全性,可以定义事件接口:
// 定义事件类型interface AppEvents { 'user:login': { userId: string; timestamp: number }; 'user:logout': { userId: string }; 'data:update': { id: string; data: unknown }; 'notification:show': { message: string; type: 'success' | 'error' | 'info' };}
// 创建类型化总线class TypedEventBus { private listeners: Map<string, Function[]> = new Map();
on<K extends keyof AppEvents>( event: K, handler: (payload: AppEvents[K]) => void ): void { if (!this.listeners.has(event)) { this.listeners.set(event, []); } this.listeners.get(event)!.push(handler); }
emit<K extends keyof AppEvents>( event: K, payload: AppEvents[K] ): void { const handlers = this.listeners.get(event); if (handlers) { handlers.forEach(handler => handler(payload)); } }
off<K extends keyof AppEvents>( event: K, handler: (payload: AppEvents[K]) => void ): void { const handlers = this.listeners.get(event); if (handlers) { this.listeners.set( event, handlers.filter(h => h !== handler) ); } }}
export const typedBus = new TypedEventBus();实际示例:通知系统
让我们考虑一个真实场景——使用事件总线创建通知系统: