作用
一个事件管理机制,用于统一进行一些事件操作。
可进行自定义事件的挂载与触发。
与写统一处理函数相比,更好管理一些,逻辑性更强。
语法
基本用法
- 引入 events 模块,该模块会暴露出一个类。
javascript
const { EventEmitter } = require('events');
- 创建出事件管理实例
ini
const eventEmit = new EventEmitter();
- 在事件管理实例之上挂载自定义事件
csharp
eventEmit.on(eventName, callback);
- 在想要用的时候可以通过实例上的 emit 方法进行事件的触发
css
eventEmit.emit(eventName, [...eventParams])
- 第一个参数表示事件名称,剩余参数会被传递给事件回调。
- EventEmitter 按照所注册的顺序同步调用所有侦听器。这样可以确保事件的正确顺序,并有助于避免竞态条件和逻辑错误。
- 当一个未注册的非 error 事件被触发时,该触发操作会被忽略。
- 在事件无用的时候使用 off 对事件进行事件的解绑
scss
eventEmit.off(eventName, callback)
两个参数都必传,参数与 dom 事件解绑的前两个参数意义一致
- 若是想移除对应事件所有的回调,则使用 removeAllListeners
scss
eventEmit.removeAllListeners(eventName)
单次事件监听 once
scss
eventEmit.once(eventName, callback)
在触发一次之后自动销毁事件。
获取当前注册事件的名称列表
scss
eventEmit.eventNames()
错误事件监听 error
普通错误事件
注册错误事件的语法与注册普通事件一致,但是当 emit 在未注册 error 事件的时候触发 error 事件时,则会导致 node 报错并退出程序
当然可以注册 error 事件,或是使用 domain 包进行处理防止程序中断
不消费错误的错误事件
我们可以使用 events 包中的 errorMonitor 来作为事件名称进行错误事件的注册。
此时我们 emit 触发 error 事件时,错误事件可以获取到错误,但是并不会将错误消费掉,该错误仍然能够导致 node 中断程序。
注册事件时回调的this值
若是注册的事件回调为一个 function 函数,则 this 值为触发 emit 时的对象。
当为箭头函数时,this 为一个空对象。
javascript
const { EventEmitter } = require('events');
class E extends EventEmitter {
a = 1;
}
const eventEmitter = new E();
const event = {m: 111};
Object.setPrototypeOf(event, eventEmitter);
eventEmitter.on('error', function(...args) {
console.log('错误', args, this);
});
event.emit('error');
css
错误 [] E { m: 111 }
处理异步事件的注册
语法
使用效果与方法
不要直接将异步事件注册为事件,因为异步事件虽然能够进行,但是若是异步事件中抛出错误时,会导致错误无法处理。
可以通过 captureRejections
选项,EventEmitter 会自动为异步事件处理器添加 .catch
逻辑,将错误路由到 error
事件或自定义的拒绝处理器,避免未处理的 Promise 拒绝:
- 若定义了
Symbol.for('nodejs.rejection')
方法,错误会传递到此方法。 - 若未定义,则触发
error
事件。 - 若未定义任何处理器,仍会抛出未处理的拒绝。
javascript
const ee2 = new EventEmitter({
captureRejections: true
});
ee2.on("something", async (value) => {
throw new Error("kaboom");
});
// 自定义拒绝处理器
ee2[Symbol.for("nodejs.rejection")] = console.log;
局部开启异步处理
在创建 EventEmitter 实例的时候在配置参数对象中指定 captureRejections 选项为 true
arduino
const ee2 = new EventEmitter({
captureRejections: true
});
全局开启异步处理
应用场景
统一的错误处理只是用于集中监控(如日志上报)和调试,避免因部分模块遗漏处理器导致问题难以定位。
语法
EventEmitter 类的静态属性 captureRejections 选项置为 true
示例
ini
const { EventEmitter } = require('events');
EventEmitter.captureRejections = true;
cookbook
- 避免在
error
事件中使用异步处理器
error
事件的处理器若为异步函数,可能引发无限错误循环(例如异步处理器自身抛出错误)。建议使用同步函数处理错误 - 全局配置的权衡:通过
events.captureRejections = true
全局启用捕获机制时,需确保所有EventEmitter
实例的error
事件或自定义拒绝处理器已正确实现。 【否则照样会报错终止程序】