Node.js从零开始-事件系统

又匆匆忙忙了两周,耽搁了不少进度,这次就先看看events这一块。

大多数Node.js的核心API都是围绕这一个通用的异步事件驱动架构的。emitters发出具名事件,然后再由函数对象listeners监听并作出响应。

发出事件的所有的对象都是EventEmitter类的实例,这些对象暴露了一个eventEmitter.on()的函数,允许1个或多个函数对象附加到这个具名事件上。

EventEmitter对象发送一个事件,所有和这个事件相关的都会被同步(synchronously)调用.

eventEmitter.on()用来注册事件监听,触发事件之后的回调。如下面的官方例子

1
2
3
4
5
6
7
8
const EventEmitter = require('events');
class MyEmitter extends EventEmitter {}

const myEmitter = new MyEmitter();
myEmitter.on('event', () => {
console.log('an event occurred!');
});
myEmitter.emit('event');

传参

eventEmitter.emit()允许随意设置参数带给listener,这个时候this会指向绑定事件的对象上——箭头函数会例外。

1
2
3
4
5
6
7
8
9
10
11
const myEmitter = new MyEmitter();
myEmitter.on('event', function(a, b) {
console.log(a, b, this);
// Prints:
// a b MyEmitter {
// domain: null,
// _events: { event: [Function] },
// _eventsCount: 1,
// _maxListeners: undefined }
});
myEmitter.emit('event', 'a', 'b');

异步VS同步

EventListener会按照注册顺序调用所有的listener,这能够确保事件的执行顺序。

可以通过process.nextTick()setImmediate()这两个方法转化为异步执行。

仅执行一次的事件

通过eventEmitter.once()来注册事件即可,当触发一次之后就会被注销。

error事件

若在EventEmitter实例中出错了,一般会发送一个error的事件,从而作出特殊的处理。

官方建议最佳实践:listener应该总是设定error事件处理,如下所示

1
2
3
4
5
6
const myEmitter = new MyEmitter();
myEmitter.on('error', (err) => {
console.error('whoops! there was an error');
});
myEmitter.emit('error', new Error('whoops!'));
// Prints: whoops! there was an error

EventEmitter类

events模块定义和暴露方法。

1
const EventEmitter = require('events');

newListenerremoveListener

newListener监听注册事件的监听器,听起来有点绕。可以这么理解,我们的房子是各个部件原料组成的,而这个是生产盖房子原料的之前的监听过程。

一个事件我们可以简单的看成有个事件名eventName,还有监听处理listener函数,当我们新注册一个事件的时候我们只要指定这两个玩意儿就能够自定义事件了。

而我们在注册之前想要搞点事情。那就可以在newListener的监听里做处理。

举个栗子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
const EventEmitter = require('events');
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter();
// Only do this once so we don't loop forever
myEmitter.once('newListener', (event, listener) => {
if (event === 'nb') {
// Insert a new listener in front
myEmitter.on('nb', () => {
console.log('大佬们');
});
}
});
myEmitter.on('nb', () => {
console.log('牛B啊!');
});
myEmitter.emit('nb');
// Prints:
// 大佬们
// 牛B啊!

这里注意要用once。不然得搞坏了。

removeListener在事件移除的时候触发。

其余api简单笔记

emitter.addListeneremitter.on(eventName, listener)的另外一种写法。

emitter.eventNames()可以查看emmitter上绑定的事件列表

emitter.prependListener()可以改变执行顺序,可以作为生命周期的一个阶段来理解。

emitter.setMaxListeners,默认情况下给一个emitter添加超过10个事件的时候就会报警,可以通过修改这个设置来避开这个报警。默认设置是为了帮助寻找内存泄漏问题。

其实就开头比较绕,下面部分都很好理解,有一个弃用的api就直接跳过不看了。官方文档解释的非常清晰,英文小菜鸡直接看也能明白~

REF

官方文档Events

坚持原创技术分享,您的支持将鼓励我继续创作!