首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

Node.js的EventEmitter 事件处理详解

在本教程中我们学习 Node.js 的原生 类。学完后你将了解事件、怎样使用   以及如何在程序中利用事件。另外还会学习 类从其他本地模块扩展的内容,并通过一些例子了解背后的原理。

本文涵盖了关于 类的所有内容。

什么是事件?

当今事件驱动的体系结构非常普遍,事件驱动的程序可以产生、检测和响应各种事件。

Node.js 的核心部分是事件驱动的,有许多诸如文件系统()和   这样的模块本身都是用 编写的。

在事件驱动的编程中,事件(event)是一个或多个动作的结果,这可能是用户的操作或者传感器的定时输出等。

我们可以把事件驱动程序看作是发布-订阅模型,其中发布者触发事件,订阅者侦听事件并采取相应的措施。

例如,假设有一个服务器,用户可以向其上传图片。在事件驱动的编程中,诸如上传图片之类的动作将会发出一个事件,为了利用它,该事件还会有 1 到 n 个订阅者。

在触发上传事件后,订阅者可以通过向网站的管理员发电子邮件,让他们知道用户已上传照片并对此做出反应;另一个订阅者可能会收集有关操作的信息,并将其保存在数据库中。

这些事件通常是彼此独立的,尽管它们也可能是相互依赖的。

什么是EventEmitter?

类是 Node.js 的内置类,位于 模块。根据文档中的描述:

大部分的 Node.js 核心 API 都是基于惯用的异步事件驱动的体系结构所实现的,在该体系结构中,某些类型的对象(称为“发射器”)发出已命名事件,这些事件会导致调用 对象(“监听器”)”

这个类在某种程度上可以描述为发布-订阅模型的辅助工具的实现,因为它可以用简单的方法帮助事件发送器(发布者)发布事件(消息)给监听器(订阅者)。

创建 EventEmitters

话虽如此,但还是先创建一个 更加实在。可以通过创建类本身的实例或通过自定义类实现,然后再创建该类的实例来完成。

创建EventEmitter对象

先从一个简单的例子开始:创建一个 ,它每秒发出一个含有程序运行时间信息的事件。

首先从 模块中导入 类:

然后创建一个 :

用这个对象发布事件非常容易:

前面已经指定了事件名,并把它发布为事件。但是程序没有任何反应,因为还没有侦听器对这个事件做出反应。

先让这个事件每秒重复一次。用  方法创建一个计时器,每秒发布一次 事件:

实例用来接受事件名称和参数。把 作为事件名, 作为自程序启动以来的时间进行传递。

通过 方法触发发射器,该方法用我们提供的信息推送事件。准备好事件发射器之后,为其订阅事件监听器:

通过 方法创建侦听器,并传递事件名称来指定希望将侦听器附加到哪个事件上。在 事件上,运行一个记录时间的方法。

函数的第二个参数是一个回调,可以接受事件发出的附加数据。

运行代码将会输出:

如果只在事件首次触发时才需要执行某些操作,也可以用 方法进行订阅:

运行这段代码会输出:

EventEmitter与多个监听器

下面创建另一种事件发送器。这是一个计时程序,有三个侦听器。第一个监听器每秒更新一次时间,第二个监听器在计时即将结束时触发,最后一个在计时结束时触发:

:每秒触发一次

:在倒数计时结束时触发

:在计时结束前 2 秒触发

先写一个创建这个事件发射器的函数:

这个函数启动了一个每秒钟发出一次 事件的事件。

第一个 用来检查计时是否已经结束并停止基于间隔的事件。如果已结束将会发布 事件。

如果计时没有结束,那么就检查计时是不是离结束还有 2 秒,如果是则发布 事件。

向该事件发射器添加一些订阅者:

这段代码将会输出:

扩展EventEmitter

接下来通过扩展 类来实现相同的功能。首先创建一个处理事件的 类:

可以在类的内部直接使用 。另外 函数用于控制计时开始的时间。否则它将在创建对象后立即开始计时。

创建一个 的新对象并订阅它:

运行程序会输出:

函数的别名是 。看一下 事件监听器:

也可以用 来完成相同的操作,例如:

EventEmitter的主要函数

eventNames()

此函数将以数组形式返回所有活动的侦听器名称:

运行这段代码会输出:

如果要订阅另一个事件,例如 ,则新事件也会添加到数组中。

这个方法不会返回已发布的事件,而是返回订阅的事件的列表。

removeListener()

这个函数可以从 中删除已订阅的监听器:

在第一个事件触发后,由于 和 都处于活动状态,这两个函数都将被执行。之后从 中删除了 。当再次发出事件时,将会只执行 :

Analiasfor is . For example, we could have written:

的别名是 。例如可以这样写:

removeAllListeners()

该函数用于从 的所有事件中删除所有侦听器:

第一个 会同时触发 和 ,因为它们当时正处于活动状态。删除它们后, 函数将发出事件,但没有侦听器对此作出响应:

错误处理

如果要在 发出错误,必须用 事件名来完成。这是 Node.js 中所有 对象的标准配置。这个事件必须还要有一个 对象。例如可以像这样发出错误事件:

事件的侦听器都应该有一个带有一个参数的回调,用来捕获 对象并处理。如果 发出了 事件,但是没有订阅者订阅 事件,那么 Node.js 程序将会抛出这个 。这会导致 Node.js 进程停止运行并退出程序,同时在控制台中显示这个错误的跟踪栈。

例如在 类中,参数的值不能小于 2,否则会无法触发 事件。在这种情况下应该发出一个 事件:

处理这个错误的方式与其他事件相同:

始终对 事件进行监听是一种很专业的做法。

使用EventEmitter的原生模块

Node.js 中许多原生模块扩展了 类,因此它们本身就是事件发射器。

一个典型的例子是 类。官方文档指出:

流可以是可读的、可写的,或两者均可。所有流都是 的实例。

先看一下经典的 Stream 用法:

但是,在写操作和 调用之间,我们添加了一个侦听器。 在完成后会发出一个 事件。在发生错误时会发出 事件,把读取流通过管道传输到写入流时会发出 事件,从写入流中取消管道传输时,会发出 事件。

另一个类是 类及其 方法:

当   写入标准输出管道时,将会触发   的 事件。当输出流遇到错误时,将从 管道发送 事件。

最后,在进程退出后,将会触发 事件。

总结

事件驱动的体系结构使我们能够创建高内聚低耦合的系统。事件表示某个动作的结果,可以定义 1个或多个侦听器并对其做出反应。

本文深入探讨了 类及其功能。对其进行实例化后直接使用,并将其行为扩展到了一个自定义对象中。最后介绍了该类的一些重要函数。

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20201015A0E5DJ00?refer=cp_1026
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券