Node.js 事件触发器模块 events

简介

触发器(Emitter)类型的对象会触发命名事件来调用函数(又称监听器,Listener)。所有能触发事件的对象都是 EventEmitter 类的实例。 这些对象有一个 eventEmitter.on() 函数,用于将一个或多个函数绑定到命名事件上。 事件的命名通常是驼峰式的字符串。


当 EventEmitter 对象触发一个事件时,所有绑定在该事件上的函数都会被同步地调用。 被调用的监听器返回的任何值都将会被忽略并丢弃。


例子,一个简单的 EventEmitter 实例,绑定了一个监听器。 eventEmitter.on() 用于注册监听器, eventEmitter.emit() 用于触发事件。使用 eventEmitter.once() 可以注册最多可调用一次的监听器。 当事件被触发时,监听器会被注销,然后再调用。

const EventEmitter = require('events');
class MyEmitter extends EventEmitter {}

const myEmitter = new MyEmitter();
myEmitter.on('event', () => {
 console.log('触发事件');
});
myEmitter.emit('event');


将参数和 this 传给监听器

eventEmitter.emit() 方法可以传任意数量的参数到监听器函数。 当监听器函数被调用时, this 关键词会被指向监听器所绑定的 EventEmitter 实例。

const myEmitter = new MyEmitter();
myEmitter.on('event', function(a, b) {
 console.log(a, b, this, this === myEmitter);
});
myEmitter.emit('event', 'a', 'b');

也可以使用 ES6 的箭头函数作为监听器。但 this 关键词不会指向 EventEmitter 实例:


异步 VS 同步

EventEmitter 以注册的顺序同步地调用所有监听器。 这样可以确保事件的正确排序,并有助于避免竞态条件和逻辑错误。 当适当时,监听器函数可以使用 setImmediate() 和 process.nextTick() 方法切换到异步的操作模式:

const myEmitter = new MyEmitter();
myEmitter.on('event', (a, b) => {
 setImmediate(() => {
  console.log('异步地发生');
 });
});
myEmitter.emit('event', 'a', 'b');


错误事件

当 EventEmitter 实例出错时,应该触发 'error' 事件。 这些在 Node.js 中被视为特殊情况。

如果没有为 'error' 事件注册监听器,则当 'error' 事件触发时,会抛出错误、打印堆栈跟踪、并退出 Node.js 进程。

const myEmitter = new MyEmitter();
myEmitter.emit('error', new Error('错误信息'));
// 抛出错误并使 Node.js 崩溃。


为了防止崩溃 Node.js 进程,可以使用 domain 模块。 (但请注意,不推荐使用 domain 模块。)

作为最佳实践,应该始终为 'error' 事件注册监听器

const myEmitter = new MyEmitter();
myEmitter.on('error', (err) => {
 console.error('错误信息');
});
myEmitter.emit('error', new Error('错误'));
// 打印: 错误信息


通过使用符号 errorMonitor 安装监听器,可以监视 'error' 事件但不消耗触发的错误。

const myEmitter = new MyEmitter();
myEmitter.on(EventEmitter.errorMonitor, (err) => {
 MyMonitoringTool.log(err);
});
myEmitter.emit('error', new Error('错误'));
// 仍然抛出错误并使 Node.js 崩溃。


捕捉 Promise 的拒绝

const ee = new EventEmitter();
ee.on('something', async (value) => {
 throw new Error('kaboom');
});


内存管理与防止泄漏

在绑定事件监听器的时候,如果监听器没有被 remove,那么存在内存泄漏的风险。


参考文档:

http://nodejs.cn/api/events.html

声明:本站所有文章和图片,如无特殊说明,均为原创发布。商业转载请联系作者获得授权,非商业转载请注明出处。
真诚赞赏,手留余香
赞赏
随机推荐
Debian11 安装笔记3:安装 MySQL 5.7
Wordpress 使用 tag 标签获取文章列表的方法
JavaScript console 的用法
Light 主题
Node.js MySQL 连接池和事务
ReferenceError: __dirname is not defined in ES module scope
WordPress 主题激活和取消激活钩子
Node.js 18.x 开始支持内置单元测试