如何使用Node.js事件发射器

98 阅读2分钟

开始使用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进程崩溃。