当前位置: 首页 > news >正文

发布订阅模式(EventEmitter)--结合生产使用

一、概述

发布订阅模式(Publish-Subscribe Pattern)是一种经典的设计模式,核心是解耦事件的发布者和订阅者,使两者无需直接依赖即可完成通信。本文档基于 TypeScript 实现了支持单页面通信的 EventEmitter,并提供完整的使用指南、API 说明和最佳实践。

核心优势

  1. 发布者(emit)只管发事件,不关心谁接收
  2. 订阅者(on/once)只管监听事件,不关心谁发送
  3. 适合:组件通信、异步通知、业务解耦

二、核心功能

方法说明
on(name, fn)订阅事件(持久)
once(name, fn)订阅一次(执行后自动销毁)
emit(name, ...args)触发事件,传参
off(name?, fn?)取消订阅
listenerCount(name)获取监听数
eventNames()获取所有事件名

三、完整代码

/** * 事件发射器核心类 * 实现事件的订阅、取消订阅、触发、一次性订阅等功能 */ class EventEmitter { /* 存储事件名与对应回调函数数组的映射,增强类型约束 */ private events:{[key:string]:Function[]}={} /* 订阅事件 */ on(eventName:string ,callback:Function):this { if(!this.events[eventName]){ this.events[eventName] = [] } this.events[eventName].push(callback) return this } /* 一次性订阅 */ once(eventName:string,callback:Function):this{ const onceCallback = (...args:any[])=>{ callback(...args) this.off(eventName,onceCallback) } return this.on(eventName,onceCallback) } /* 取消订阅 */ off(eventName?:string ,callback?:Function):this{ if(!eventName){ /* 清除所有事件 */ this.events = {} return this } if(!callback){ /* 清除指定事件的所有回调 */ delete this.events[eventName] return this } /* 移除指定回调 */ const callbacks = this.events[eventName] if(callbacks){ const index = callbacks.indexOf(callback) if(index>-1){ callbacks.splice(index,1) } } return this } /* 触发事件 */ emit(eventName:string,...args:any[]):this{ const callbacks = this.events[eventName] if(callbacks){ callbacks.forEach(callback=>{ try { callback(...args) } catch (error) { console.log(`Error in event ${eventName}:`,error) } }) } return this } /* 获取事件监听器数量 */ listenerCount(eventName:string):number{ return this.events[eventName]?.length||0 } /* 获取所有事件名 */ eventNames():string[]{ return Object.keys(this.events) } } /* eventCenter (单例 + DOM风格API)*/ class EventCenter extends EventEmitter { addEventListener(eventName:string,callback:Function):this{ return this.on(eventName,callback) } removeEventListener(eventName:string,callback?:Function):this{ return this.off(eventName,callback) } dispatchEvent(eventName:string,data?:any):this{ return this.emit(eventName,data) } } /* 创建单例实例 */ const eventCenter = new EventCenter() export default eventCenter

使用示例:

import eventCenter from './simple-event-center' // 订阅事件 const handler = (data) => { console.log('收到消息:', data) } eventCenter.addEventListener('message', handler) // 触发事件 eventCenter.dispatchEvent('message', { text: 'Hello World' }) // 一次性订阅 eventCenter.once('once-event', (data) => { console.log('只执行一次:', data) }) // 取消订阅 eventCenter.removeEventListener('message', handler)

四、注意点

本方法在跨浏览器标签页 / 窗口无法直接正常使用,仅支持单页面使用

核心原因:每个浏览器标签页 / 窗口都是独立的 JavaScript 执行环境,你的eventCenter是单个页面内的单例对象,不同页面的eventCenter内存空间完全隔离 ——A 页面发布的事件,B 页面的eventCenter根本接收不到。

举个直观例子:

  • 标签页 1:eventCenter.emit('user:login', {name: '张三'})→ 只有标签页 1 内的订阅者能收到;
  • 标签页 2:eventCenter.on('user:login', (data) => console.log(data))→ 永远收不到标签页 1 的事件。

想要实现跨页面通信:

方案核心 API适用场景优点缺点
1. localStorage + storage 事件localStorage.setItem+window.addEventListener('storage')同域名下的跨标签页简单、无需处理跨域、兼容性好只能同域名、数据存在本地
2. postMessagewindow.postMessage跨域名 /iframe/ 窗口支持跨域、灵活需要获取目标窗口的引用
http://www.jsqmd.com/news/449752/

相关文章:

  • 地表土装袋机设计
  • 大一双非本求助
  • java树形死循环问题的解决
  • C++——内存管理和初阶模板
  • “车道偏离预警系统-LDW的simulink与CarSim联合仿真模型及其驾驶员风格判断研究”...
  • 探究平面等离子体手性纳米材料结构与COMSOL模型之关联
  • 比迪丽LoRA多场景落地:儿童读物插画、青少年美育课程AI辅助工具
  • LLaVA-v1.6-7B开源部署指南:适配消费级RTX4090的轻量级方案
  • 手把手造个PLC电梯控制系统
  • AI Agent开发路线图2026:从入门到精通,一文读懂智能体技术
  • conda 中的环境迁移(Linux)
  • 基于深度学习的护目镜佩戴识别检测系统|全新web界面|多模态|AI大模型智能分析|YOLOv8、YOLOv10、YOLOv11、YOLOv12
  • 【SpringBoot】带你一文彻底搞懂RestController和Controller的关系与区别
  • Java Util Concurrent(JUC)
  • 面试题:互斥锁与条件变量,在生产者消费者模型中的使用,lock在条件变量中的作用
  • UE5 编辑器下添加组件
  • 计算机毕业设计springboot校园疫情防范管理系统 高校疫情防控数字化管理平台 基于Spring Boot的校园防疫信息管理系统
  • WebRTC 视频编码丢帧与降低分辨率机制深度剖析
  • 甩锅防御机制:运维说“网络正常”时的专业应对策略
  • IPTV系统解决方案怎么选?从机顶盒到系统平台全解析
  • 计算机毕业设计springboot高校智慧党建管理系统 基于SpringBoot的数字化高校党务工作平台 SpringBoot驱动的大学党建信息化综合服务平台
  • GISBox vs GeoServer:谁才是现代GIS开发的更优解?
  • 大兴机场机位进出方案优化设计研究
  • jQuery day1
  • OpenAI GPT-5.4实测
  • 粉色PCB评测排名:猎板技术可靠,兼具颜值与性能
  • 从“踩坑无数”到“如获至宝”:我如何找到那家真正靠谱的AI服务商?
  • 毕业论文神器!冠绝行业的降AIGC平台 —— 千笔·降AI率助手
  • 内网两台 Linux 服务器高效传输大文件(70GB 实战指南)
  • LEDNum不是二进制数