开始使用Node.js事件发射器
Node.js有一个异步的事件驱动架构。这就允许在设计中,因某个动作而发出的事件可以导致监听器对象被执行。Node.js有一个内置模块events 。这个模块有一个对象Event Emitter ,我们可以操作它来监听事件。
前提条件
本文假设你有JavaScript的基本知识,REPL,以及在本地开发环境中安装了Node.js。
事件发射器对象
Event Emitter 对象位于events 模块中。它有一个eventEmitter.on() 方法,它公开了这个方法,以允许将函数附加到发射的事件上。
让我们从导入events 模块开始。
~$ node
Welcome to Node.js v15.12.0.
Type ".help" for more information.
> const events = require('events');
undefined
> const eventEmitter = new events.EventEmitter();
undefined
>
在上面的脚本中,我们首先导入events 模块。然后我们创建一个事件发射器类的实例。
另外,我们也可以导入events 模块,并用我们自定义的myEventEmitter 类来扩展主类,如下图所示。
$ node
Welcome to Node.js v15.12.0.
Type ".help" for more information.
> const EventEmitter = require('events');
undefined
> class MyEventEmitter extends EventEmitter {}
undefined
> const myEventEmitter = new MyEmitter();
undefined
> myEventEmitter.on('event', () => {
... console.log('an event emitted!');
... });
> myEventEmitter.emit('event');
值得注意的是,Node.js中的任何事件发射对象都是Event Emitter类的一个成员。
发出事件
Node.js中的事件概念是非常直接的。事件发射对象会发射命名的事件。这些事件会导致先前注册的监听器被调用。
让我们来看看一个事件发射的例子。
$ node
Welcome to Node.js v15.12.0.
Type ".help" for more information.
> const eventEmitter = require(`events`);
undefined
> class MyEventEmitter extends eventEmitter{}
undefined
> const myEmitter = new MyEventEmitter();
undefined
> function myFirstEvent(){
... console.log(`my first event occurred`);
... }
undefined
> function mySecondEvent(){
... console.log(`hooray, another event has occured`);
... }
undefined
> myEmitter.on('event', myFirstEvent);
MyEventEmitter {
_events: [Object: null prototype] { event: [Function: c1] },
_eventsCount: 1,
_maxListeners: undefined,
[Symbol(kCapture)]: false
}
> myEmitter.on('event', myFirstEvent);
MyEventEmitter {
_events: [Object: null prototype] {
event: [ [Function: myFirstEvent], [Function: myFirstEvent] ]
},
_eventsCount: 1,
_maxListeners: undefined,
[Symbol(kCapture)]: false
}
>
当我们发射event 事件时,myFirstEvent() 和mySecondEvent() 的回调应被调用。
输出。
--------------------------
> myEventEmitter.emit(`event`);
my first event occurred
hooray, another event has occurred
true
>
注册的事件只被触发一次,使用once
以前,我们讨论过,事件监听器在每次发出它们所依附的事件时被调用。
存在这样的场景,我们只需要执行这些监听器一次。在这些情况下,我们利用eventEmitter.once() 。
让我们看一个例子。
--------------------
>myEventEmitter.once('MyOnceEvent', () => console.log('my once event fired'));
发出MyOnceEvent 事件。
-----------------------
> myEventEmitter.emit('MyOnceEvent');
输出。
my one event fired
让我们试着再次发射这个事件。
> myEventEmitter.emit('MyOnceEvent');
该事件已经发射过一次,不能再次发射,结果是空白屏幕。
用回调参数注册事件
eventEmitter.emit()方法允许监听器函数被传递参数。让我们来看看如何实现这个功能。
myEventEmitter.on('status', (statusCode, statusMsg)=> console.log(`Status code = ${code} while message= ${statusMsg}`));
myEventEmitter {
_events: [Object: null prototype] { status: [Function (anonymous)] },
_eventsCount: 1,
_maxListeners: undefined,
[Symbol(kCapture)]: false
}
>
传递参数。
----------------
> myEventEmitter.emit('status', 201, 'created');
>
输出。
Status code =201 while message= created
错误事件
每当EventEmitter实例内发生错误时,就会发出错误事件。如果一个eventEmitter ,没有注册的错误事件,将发出一个error ,退出Node.js进程。
让我们看一个例子。
---------------------------------------------
> myEmitter.emit('error', new Error('whoops, an error instance!'));
Uncaught [Error: an error instance!] {
domainEmitter: MyEventEmitter {
_events: [Object: null prototype] {},
_eventsCount: 0,
_maxListeners: undefined,
[Symbol(kCapture)]: false
},
domainThrown: false
}
> false
>
你会注意到一个错误被抛出,因为我们没有任何监听器来处理这个错误。
取消注册事件
现在我们已经看到了如何创建事件,如果我们需要取消注册它们呢?为了取消我们之前创建的event ,我们调用eventEmitter.off() 方法并将其传递给事件,如下图所示。
myEmitter.off('event', myFirstEvent); // if you try emitting this event, nothing happens
总结
在本教程中,我们讨论了EventEmitter 对象。使用这个对象,我们能够创建一个事件,发射一个事件,并监听它。
我们还简单地看了一下错误事件,它导致Node.js进程崩溃。