JavaScript 中的事件发射器 (Event Emitters)

2025年2月15日 | 阅读 6 分钟

概述

在 Node.js 中,事件发射器是对象,它们通过发送消息来指示动作的完成。JavaScript 程序员可以编写代码来侦听来自事件发射器的事件,然后在每次事件触发时触发函数。在这种情况下,事件由一个标识符字符串和任何需要发送给侦听器的数据组成。

当我们在 Node.js 中希望一个动作在另一个动作完成后发生时,我们通常会使用**异步编程**技术,例如嵌套回调或链式 Promise。然而,这些方法将触发和结果动作紧密耦合,使得以后更改结果动作变得困难。组织这种关系的一种替代方法是通过**事件发射器**,它使用发布-订阅模式。发布者(也称为事件发射器)发送消息或事件,订阅者接收它并对其做出响应。这就是软件架构模式的应用。此模式的优点在于它消除了发布者需要了解订阅者的需要。当发布者发布消息时,由订阅者来做出相应的响应。如果我们想改变应用程序的行为方式,就不需要更换发布者;我们只需要改变订阅者如何响应事件。

在本文中,我们将学习如何为 JavaScript 的**TicketManager**类编写事件侦听器,该类允许购买门票。当门票被购买时,将触发 buy 事件,并为该事件设置侦听器。此外,此过程还将演示如何处理来自源的事件订阅者和不正确的事件。

目录

  1. 理解 EventEmitter
  2. EventEmitter 的基本概念
  3. 使用 addListener 创建监听事件
  4. 移除事件的实例
  5. 高级 EventEmitter 功能
  6. 使用 EventEmitter 的最佳实践
  7. 总结

Node.js 以其事件驱动的异步架构而闻名,该架构能够处理多个操作而不会干扰其他任务的完成。`events` 模块中的 EventEmitter 类构成了此架构的基础。Node.js 的许多核心功能,例如文件操作和服务器框架,都支持此核心组件。

理解 EventEmitter

EventEmitter 使事件处理变得简单而灵活。它可以比作发布-订阅模式,其中

  1. 发射器会发布命名事件。
  2. 侦听器将回调函数附加到这些事件以订阅(处理)它们。

这种机制通过实现不同应用程序组件之间的解耦通信来提高模块化和可扩展性。

语法

EventEmitter 的基本概念

事件触发:事件触发后,所有注册的侦听器都会收到通知。

事件侦听:您可以为特定事件设置回调函数或侦听器。当匹配的事件被触发时,这些侦听器会收到通知。

移除侦听器:如果不再需要侦听器,您也可以移除它们,这有助于有效的资源管理。

使用 addListener 创建监听事件

为了响应事件,我们首先需要创建一个侦听器,它将接收触发的回调并采取必要的后续操作。EventEmitter 的 **addListener** 属性允许我们创建事件侦听器。addListener 非常有用,因为它通过将其添加到数组的末尾,避免了我们多次编写事件。它允许我们多次调用 addListener 来调用多个事件实例。

触发事件:由于 Node.js 中的每个事件都是一个命名事件,我们可以使用 emit 方法来启动一个事件,并将任何参数传递给事件的监听函数。

语法

示例:这演示了如何使用 addListener 方法添加事件并创建一个 EventEmitter。

代码

输出

Event Emitters in JavaScript

移除事件的实例

如果我们想删除特定事件的侦听器,我们可以使用 **removeListener** 方法。或者,我们可以使用 **removeAllListeners** 方法来删除事件的所有侦听器实例。

语法

示例:一个移除事件侦听器的例子。

代码

输出

Event Emitters in JavaScript

如您所见,上面的输出显示,虽然事件被调用了两次,但输出只出现了一次,因为我们移除了事件侦听器,这意味着当事件被触发两次时没有侦听器在场。

高级 EventEmitter 功能

EventEmitter 支持高级功能,例如管理多个侦听器、错误处理等。

包含更多侦听器

对于同一个事件,您可以添加多个侦听器,它们将按照添加的顺序被调用。

代码

输出

Event Emitters in JavaScript

一次性侦听器

once 方法添加的侦听器在仅使用一次后就会被移除,下一次事件触发时。

代码

输出

Event Emitters in JavaScript

移除侦听器

removeListener 方法允许您删除单个侦听器,而 removeAllListeners 方法删除事件的所有侦听器。

代码

输出

Event Emitters in JavaScript

使用 EventEmitter 的最佳实践

限制侦听器数量:为防止内存泄漏,请尽量减少侦听器数量。要管理最大侦听器数量,请使用 **setMaxListeners**。

正确处理错误:为确保能够优雅地捕获和处理错误,请始终提供错误侦听器。

移除未使用的侦听器:为释放资源,请移除不再需要的侦听器。

使用有意义且描述性的事件名称:为了提高可读性和可维护性,请为事件指定有意义的、描述性的名称。

总结

在本教程中,您了解了如何使用 Node.js 事件发射器来触发事件。通过使用 EventEmitter 对象的 emit() 函数,您触发了事件,然后使用 on() 和 once() 函数来监听事件并在每次事件触发时运行代码。此外,您还为错误事件设置了侦听器,并使用 listenerCount() 函数来跟踪和管理侦听器。

为了使用回调和 Promise 实现相同的功能,我们的门票管理系统需要与数据库和电子邮件服务模块集成。由于我们使用了事件发射器,事件与实现是分离的。此外,任何拥有门票管理器访问权限的模块都可以监视其事件并对其做出响应。如果您希望内部或外部 Node.js 模块能够看到您对象的操作,请为您对象创建一个事件发射器。这将有助于扩展性。