Node.js EventEmitter


Node.js All asynchronous I/O operations will send an event to the event queue when completed.

Many objects in Node.js will emit events: a net.Server object will emit an event every time there is a new connection, and a fs.readStream object will emit an event when the file is opened. All of these event-generating objects are instances of events.EventEmitter.


EventEmitter class

The events module only provides one object: events.EventEmitter. The core of EventEmitter is the encapsulation of event triggering and event listener functions.

You can access this module through require("events");.

// 引入 events 模块
var events = require('events');
// 创建 eventEmitter 对象
var eventEmitter = new events.EventEmitter();

EventEmitter object will trigger the 'error' event if an error occurs during instantiation. The 'newListener' event is fired when a new listener is added, and the 'removeListener' event is fired when a listener is removed.

Below we use a simple example to illustrate the usage of EventEmitter:

//event.js 文件
var EventEmitter = require('events').EventEmitter; 
var event = new EventEmitter(); 
event.on('some_event', function() { 
	console.log('some_event 事件触发'); 
}); 
setTimeout(function() { 
	event.emit('some_event'); 
}, 1000);

The execution results are as follows:

Run this code, and the console outputs after 1 second 'some_event event triggers'. The principle is that the event object registers a listener for the event some_event, and then we use setTimeout to send the event some_event to the event object after 1000 milliseconds. At this time, the listener for some_event will be called.

$ node event.js 
some_event 事件触发

Each event of EventEmitter consists of an event name and several parameters. The event name is a string, which usually expresses certain semantics. For each event, EventEmitter supports several event listeners.

When an event is triggered, the event listeners registered to this event are called in sequence, and the event parameters are passed as callback function parameters.

Let us explain this process with the following example:

//event.js 文件
var events = require('events'); 
var emitter = new events.EventEmitter(); 
emitter.on('someEvent', function(arg1, arg2) { 
	console.log('listener1', arg1, arg2); 
}); 
emitter.on('someEvent', function(arg1, arg2) { 
	console.log('listener2', arg1, arg2); 
}); 
emitter.emit('someEvent', 'arg1 参数', 'arg2 参数');

Execute the above code, the running results are as follows:

$ node event.js 
listener1 arg1 参数 arg2 参数
listener2 arg1 参数 arg2 参数

In the above example, the emitter registered two events for someEvent event listener, and then the someEvent event is triggered.

You can see in the running results that two event listener callback functions are called successively. This is the simplest usage of EventEmitter.

EventEmitter provides multiple properties, such as on and emit. The on function is used to bind the event function, and the emit attribute is used to trigger an event. Next, let’s take a closer look at the properties of EventEmitter.

Method

##4##5removeAllListeners([event])6setMaxListeners(n)7listeners(event)8emit(event, [arg1], [arg2], [...])Class method
Serial NumberMethod & Description
1addListener(event, listener)
Add a listener to the end of the listener array for the specified event.
2on(event, listener)
Register a listener for the specified event, accepting a string event and a callback function.
server.on('connection', function (stream) {
  console.log('someone connected!');
});
3once(event, listener)
Register a one-time listener for the specified event, that is, the listener can only It will be triggered once, and the listener will be released immediately after being triggered.
server.once('connection', function (stream) {
  console.log('Ah, we have our first user!');
});
removeListener(event, listener)Remove a listener for the specified event. The listener must be the A listener for the event that has been registered.
var callback = function(stream) {
  console.log('someone connected!');
};
server.on('connection', callback);
// ...
server.removeListener('connection', callback);

Remove all listeners for all events. If the event is specified, move All listeners except the specified event.
By default, EventEmitters will output a warning if you add more than 10 listeners information. The setMaxListeners function is used to increase the default limit of the number of listeners.
Returns the listener array for the specified event.
In the order of parameters Execute each listener and return true if the event has a registered listener, otherwise return false.

Serial number1listenerCount(emitter, event)Event
Method & Description
Returns the number of listeners for the specified event.

Serial Number1newListener2removeListener

Example

The following example demonstrates the application of the EventEmitter class through the connection event.

Create the main.js file, the code is as follows:

var events = require('events');
var eventEmitter = new events.EventEmitter();

// 监听器 #1
var listener1 = function listener1() {
   console.log('监听器 listener1 执行。');
}

// 监听器 #2
var listener2 = function listener2() {
  console.log('监听器 listener2 执行。');
}

// 绑定 connection 事件,处理函数为 listener1 
eventEmitter.addListener('connection', listener1);

// 绑定 connection 事件,处理函数为 listener2
eventEmitter.on('connection', listener2);

var eventListeners = require('events').EventEmitter.listenerCount(eventEmitter,'connection');
console.log(eventListeners + " 个监听器监听连接事件。");

// 处理 connection 事件 
eventEmitter.emit('connection');

// 移除监绑定的 listener1 函数
eventEmitter.removeListener('connection', listener1);
console.log("listener1 不再受监听。");

// 触发连接事件
eventEmitter.emit('connection');

eventListeners = require('events').EventEmitter.listenerCount(eventEmitter,'connection');
console.log(eventListeners + " 个监听器监听连接事件。");

console.log("程序执行完毕。");

The above code, the execution result is as follows:

$ node main.js
2 个监听器监听连接事件。
监听器 listener1 执行。
监听器 listener2 执行。
listener1 不再受监听。
监听器 listener2 执行。
1 个监听器监听连接事件。
程序执行完毕。

error event

EventEmitter A special event error is defined, which contains error semantics. When we encounter The error event is usually triggered when an exception occurs.

When error is triggered, EventEmitter stipulates that if there is no response If the corresponding listener is used, Node.js will treat it as an exception, exit the program and output an error message.

We generally need to trigger error Set a listener on the event object to avoid the entire program crashing when an error is encountered. For example:

var events = require('events'); 
var emitter = new events.EventEmitter(); 
emitter.emit('error');

The following error will be displayed when running:

node.js:201 
throw e; // process.nextTick error, or 'error' event on first tick 
^ 
Error: Uncaught, unspecified 'error' event. 
at EventEmitter.emit (events.js:50:15) 
at Object.<anonymous> (/home/byvoid/error.js:5:9) 
at Module._compile (module.js:441:26) 
at Object..js (module.js:459:10) 
at Module.load (module.js:348:31) 
at Function._load (module.js:308:12) 
at Array.0 (module.js:479:10) 
at EventEmitter._tickCallback (node.js:192:40)

Inherit EventEmitter

Most of the time we will not use EventEmitter directly, but inherit it in the object it. Including fs, net, Including http, as long as the core modules that support event response are subclasses of EventEmitter.

Why do we do this? There are two reasons:

First, the object implementation event with a certain entity function conforms to the semantics. Event listening and emitting should be methods of an object.

Secondly, JavaScript’s object mechanism is based on prototypes and supports Partial multiple inheritance, inheriting EventEmitter will not disrupt the original inheritance relationship of the object.

Event & Description

  • event

    - String, event name

  • listener

    - Event handling function

  • This event is triggered when a new listener is added.


    ##event
  • - Characters String, event name

  • listener
  • - Event processing function

    Removes a listener from the specified listener array. It should be noted that this operation will change the index of those listeners after the deleted listener.