当前位置:首页 > 技术分析 > 正文内容

好好了解一下 EventEmitter(好好了解一下怎么回)

ruisui882个月前 (05-04)技术分析22

在 JavaScript 中,EventEmitter 是一个事件驱动编程的核心工具,用于实现对象间的发布-订阅(Pub/Sub)模式。它允许对象监听和触发自定义事件,常用于异步通信、模块解耦等场景。

1. EventEmitter 的核心概念

  • 事件(Event):一个标识符(如 'message' 或 'error'),表示某种行为或状态变化。
  • 监听器(Listener):绑定到事件的回调函数,当事件触发时执行。
  • 触发(Emit):主动调用某个事件,执行所有绑定的监听器。

2. 原生 EventEmitter 的使用

在 Node.js 中,EventEmitterevents 模块的内置类。浏览器环境无原生支持,但可手动实现或使用第三方库(如 EventTarget)。

Node.js 示例


const EventEmitter = require('events');


// 创建实例

class MyEmitter extends EventEmitter {}

const emitter = new MyEmitter();


// 监听事件

emitter.on('message', (data) => {

console.log('收到消息:', data);

});


// 触发事件

emitter.emit('message', 'Hello World!'); // 输出: 收到消息: Hello World!


3. 浏览器的替代方案

(1) 使用 EventTarget(浏览器原生 API)


const eventTarget = new EventTarget();


// 监听事件

eventTarget.addEventListener('click', (e) => {

console.log('事件数据:', e.detail);

});


// 触发自定义事件

const event = new CustomEvent('click', {

detail: { x: 100, y: 200 } // 可携带数据

});

eventTarget.dispatchEvent(event);


(2) 手动实现简单 EventEmitter


class EventEmitter {

constructor() {

this.events = {}; // 存储事件及监听器

}


// 监听事件

on(eventName, listener) {

if (!this.events[eventName]) {

this.events[eventName] = [];

}

this.events[eventName].push(listener);

}


// 触发事件

emit(eventName, ...args) {

const listeners = this.events[eventName];

if (listeners) {

listeners.forEach(listener => listener(...args));

}

}


// 移除监听器

off(eventName, listenerToRemove) {

const listeners = this.events[eventName];

if (listeners) {

this.events[eventName] = listeners.filter(

listener => listener !== listenerToRemove

);

}

}

}


// 使用示例

const emitter = new EventEmitter();

emitter.on('log', (message) => {

console.log('日志:', message);

});

emitter.emit('log', '用户登录'); // 输出: 日志: 用户登录


4. EventEmitter 的关键方法

方法

作用

.on(event, listener)

绑定事件监听器

.once(event, listener)

绑定一次性监听器(触发后自动移除)

.emit(event, [...args])

触发事件,并传递参数

.off(event, listener)

移除指定事件的某个监听器

.removeAllListeners()

移除所有监听器

5. 在前端代码中的用途

在之前的 WebRTC 示例中,EventEmitter 被用作信令通道的模拟,实际项目中需替换为真正的网络通信(如 WebSocket):


// 示例中的模拟信令通道

const signaling = new EventEmitter();


// 发送 Offer(模拟网络传输)

signaling.emit('offer', offerDescription);


// 接收 Answer(模拟网络接收)

signaling.on('answer', (answer) => {

pc.setRemoteDescription(answer);

});


6. 注意事项

内存泄漏
不使用的监听器需通过
.off() 主动移除,否则可能因对象无法回收导致内存泄漏。

异步触发
监听器的执行是同步的,若需异步操作,需自行封装(如用
setTimeoutPromise)。

错误处理
建议始终监听
'error' 事件,避免未捕获的异常导致进程崩溃(Node.js 中尤为重要):


emitter.on('error', (err) => {

console.error('发生错误:', err);

});


7. 常见应用场景

  • UI 组件通信:父子组件间传递数据(如 Vue/React 中的事件总线)。
  • 网络通信:封装 WebSocket 消息的发布-订阅。
  • 状态管理:Redux 或 Vuex 中响应状态变化。
  • 异步任务协调:多个异步操作完成后触发事件。

总结一下

EventEmitter 是 JavaScript 事件驱动编程的基石,无论是 Node.js 后端还是前端复杂交互,它都能通过解耦代码逻辑提升可维护性。实际开发中,可根据场景选择原生 API、手动实现或第三方库(如 mittEventEmitter3)。

爱学习小伙伴更多精彩关注不迷路哟~

扫描二维码推送至手机访问。

版权声明:本文由ruisui88发布,如需转载请注明出处。

本文链接:http://www.ruisui88.com/post/3800.html

分享给朋友:

“好好了解一下 EventEmitter(好好了解一下怎么回)” 的相关文章

vue3中父子传值、defineProps用法、defineEmits用法

Vue3中新增了一个 script setup 语法糖模式,可以在单文件组件中更简洁地编写组件逻辑。使用 script setup 语法后,props、data、computed、methods 等选项不再需要独立定义,而是可以直接在 setup 函数中声明,代码结构更加清晰,并且可以更方便地使用响...

K8s里我的容器到底用了多少内存?

作者:frostchen导语 Linux下开发者习惯在物理机或者虚拟机环境下使用top和free等命令查看机器和进程的内存使用量,近年来越来越多的应用服务完成了微服务容器化改造,过去查看、监控和定位内存使用量的方法似乎时常不太奏效。如果你的应用程序刚刚迁移到K8s中,经常被诸如以下问题所困扰:容器的...

我的VIM配置

写一篇关于VIM配置的文章,记录下自己的VIM配置,力求简洁实用。VIM的配置保存在文件~/.vimrc中(Windows下是C:\Users\yourname \_vimrc)。VIM除了自身可配置项外,还可插件扩展。VIM的插件一般用vundle或vim-plug来管理,但我力求简单,不打算装太...

《暗黑破坏神 2:重制版》PC 版 2.3 版本发布,支持英伟达 DLSS

IT之家 12 月 3 日消息,暴雪为《暗黑破坏神 2:重制版》PC 版发布了更新 2.3 版本,添加了“离线难度缩放”滑块(玩家可以在单人游戏时增加挑战和奖励的级别)、多项辅助功能和用户界面改进,以及英伟达 DLSS 支持。玩法改进:玩家现在可以在离线游戏的选项菜单中使用“游戏难度等级”,它提供与...

vue-router是如何解析query参数呢? #前端

vue-router 中的 query 解析。1. 大家好,我是龙仔。今天来分享 vue-router 是如何解析快乐参数的,因为使用 vue 路由会传 query 参数和快乐参数,所以从 vue 的角度来看如何解析传递的快乐参数。2. 基础知识大家应知道,快乐参数结构如:a、b、c、a、b、c、a...

Vue2的16种传参通信方式

前言先直入主题列出有哪些传参方式,下面再通过事例一一讲解。props(父传子)$emit与v-on (子传父)EventBus (兄弟传参).sync与update: (父子双向)v-model (父子双向)ref$children与$parent$attrs与$listeners (爷孙双向)pr...