持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第3天,点击查看活动详情
event模块是node中核心模块之一,大部分的核心API都依赖event模块进行异步执行。它通常是作为一种基类,被其他模块继承的。
例如http模块接收post数据或者是错误捕捉:
const http = require('http');
const server = http.createServer((req, res) => {
let buf = Buffer.from([]);
req.on('data', (chunk) => {
buf = Buffer.concat([buf, chunk]);
});
req.on('end', () => {
console.log(buf.toString());
});
});
event模块在node中几乎无处不在,所以他在node中非常重要。那么现在就来了解一下node中的event吧~
工作原理
与普通的发布订阅模式相同,event对象中有两种概念:监听器与触发器。
监听器的作用就是给event新增一个监听事件,当触发器触发对应事件时调用已经声明的监听器。
而触发器是用于触发对应事件的。
所以,event模块的工作原理如下图:
模块构成
event模块包含EventEmitter类,还有一些全局event的方法
1.EventEmitter类
EventEmitter是一个提供事件监听与触发事件的类。
实例化时接收一个参数captureRejections,表示是否接受自动promise的reject
const { EventEmitter } = require('events');
const myEvent = new EventEmitter({
// 是否接受自动promise的`reject`
captureRejections: true
})
当我们创建一个新的EventEmitter实例对象后,我们就可以在event对象中新增监听器与触发监听器
addListener&on方法,用于向event对象中添加一个监听器,一个event对象可以添加多个同名的监听器,当触发时会依次触发添加的监听器。一般来说,监听器的数量是有限制的,默认为10,当然也可以通过设置改变监听器的最大数量。
const { EventEmitter } = require('events');
const myEvent = new EventEmitter();
myEvent.on('event', () => {
console.log('event 1');
});
myEvent.addListener('event', () => {
console.log('event 2');
});
myEvent.emit('event');
// event 1
// event 2
emit用于触发已经添加的监听器。
addListener 与 emit 是 event 对象中最核心的方法。用于新增与触发监听器。
- event其他方法
| 方法名 | 作用 |
|---|---|
| eventNames | 获取事件中所有监听器的名字 (string| Symbol)[] |
| getMaxListeners | 获取添加监听器最大数量 |
| listererCount(eventName) | 获取对应事件名的监听器数量 |
| listeners(eventName) | 获取对应事件监听器的副本 |
| removeListener(eventName) | 删除对应名称的监听器 |
| off | 同removeListener |
| once | 添加只会触发一次的事件监听器 |
| prependListener | 向监听器数组头部插入新的监听器 |
| prependOnceListener | 向监听器数组头部插入新的只触发一次的监听器 |
| removeAllListeners([listeners]) | 删除数组中的所有监听器 |
| setMaxListeners | 设置最大的监听器数量 |
| rawListeners(eventName) | 返回对应事件的监听器数组的副本 |
2. event全局方法
event 全局方法用于修改和获取event模块的一些全局配。比如修改和获取最大监听器数量,添加对应event对象的监听器等等...
event.on用于添加指定event事件的监听器
const event = require('events');
const { EventEmitter } = event;
const myEvent = new EventEmitter();
const listener = event.on(myEvent, 'test');
listener.next().then((val) => {
console.log(val, ' hello');
});
myEvent.emit('test', '123', '456');
// { value: [ '123', '456' ], done: false } hello
setMaxListeners(nums, [...eventEmitter])设置对应event对象的最大监听器
const event = require('events');
const { EventEmitter } = event;
const myEvent = new EventEmitter();
event.setMaxListeners(2, myEvent);
myEvent.on('test', (...args) => {
console.log(args);
});
myEvent.on('test', (...args) => {
console.log(args);
});
myEvent.on('test', (...args) => {
console.log(args);
});
myEvent.emit('test', '123', '456');
// warnning
- 其他event方法
| 方法名 | 作用 |
|---|---|
| getEventListeners(emitterOrTarget, eventName) | 返回名为eventName的事件的监听器数组的副本。 |
| defaultMaxListeners | 直接修改默认最大监听器数量 |
| errorMonitor | 用于异常捕捉 |
| once(emitter, name) | 添加一个只执行一次的监听器 |
模拟实现event模块
了解了event的api与工作原理,下面就来实践一下:编写一个异步的处理的方法,并新增一个在event当处理完成后进行触发事件。
const event = require('events');
const myEvent = new event.EventEmitter();
class ComplexEvent {
constructor() {
this.event = myEvent;
}
handleCall = function () {
// do something...
this.event.emit('call');
};
handleEvent = function () {
return new Promise((resolve) => {
// do something...
this.event.emit('data', 123);
setTimeout(() => {
resolve();
this.event.emit('end');
}, 1000);
});
};
handleEnd = function () {
// do something...
this.event.emit('end');
};
}
const complexEvent = new ComplexEvent();
complexEvent.event.on('call', () => {
console.log('on call');
});
complexEvent.event.on('data', (data) => {
console.log('on data', data);
});
complexEvent.event.on('end', () => {
console.log('on end');
});
complexEvent.handleCall();
complexEvent.handleEvent();
// on call
// on data 123
// on end
总结
- event是一个用于异步执行触发事件的模块,是一个很标准的发布—订阅设计模式
- event通常用于基类的继承
- eventEmitter类,event方法介绍
- event模块实战