Node.js EventEmitter

All asynchronous I/O operations in Node.js send an event to the event queue when they complete.

Many objects in Node.js dispatch events: a net.Server object emits an event every time a new connection is established, and an fs.readStream object emits an event when a file is opened. All of these objects that produce events are instances of events.EventEmitter.

EventEmitter is a core module in Node.js used for creating, registering, and triggering events.

EventEmitter is the foundation of event-driven programming and helps developers easily implement event publishing and subscription mechanisms.


EventEmitter Class

The events module provides only one object: events.EventEmitter.

The core of EventEmitter is the encapsulation of event triggering and event listener functionality.

You can userequire("events");to access this module.

Example

// Import the events module
var events = require('events');
// Create an eventEmitter object
var eventEmitter = new events.EventEmitter();

If an error occurs while instantiating an EventEmitter object, the error event is emitted. The newListener event is emitted when a new listener is added, and the removeListener event is emitted when a listener is removed.

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

Example

//event.js file
var EventEmitter = require('events').EventEmitter;
var event = new EventEmitter();
event.on('some_event', function() {
        console.log('some_event event triggered');
});
setTimeout(function() {
        event.emit('some_event');
}, 1000);

After running this code, the console outputs the following after 1 second:some_event event triggeredThe principle is that the event object registers a listener for the some_event event. Then, after 1000 milliseconds, we send the some_event event to the event object via setTimeout, at which point the some_event listener is called.

The execution result is as follows:

$ node event.js 
some_event 事件触发

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

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

Let us explain this process with the following example:

Example

//event.js file
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 parameter', 'arg2 parameter');

Running the above code produces the following result:

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

In the above example, emitter registers two event listeners for the event someEvent, and then triggers the someEvent event.

From the running result, you can see that the two event listener callback functions are called one after another. This is the simplest usage of EventEmitter.

EventEmitter provides several properties, such asonandemit。ona function for binding event handlers,emitand a property for triggering an event. Next, let us take a closer look at the EventEmitter properties.

Methods

No.Method & Description
1addListener(event, listener)
Adds a listener for the specified event to the end of the listener array.
2on(event, listener)
Registers 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)
Registers a one-time listener for the specified event, meaning the listener will be triggered at most once and is immediately removed after being triggered.
server.once('connection', function (stream) {
  console.log('Ah, we have our first user!');
});
4removeListener(event, listener)

Removes a listener for the specified event. The listener must have already been registered for that event.

It accepts two parameters: the first is the event name, and the second is the callback function name.

var callback = function(stream) {
  console.log('someone connected!');
};
server.on('connection', callback);
// ...
server.removeListener('connection', callback);
5removeAllListeners([event])
Removes all listeners for all events. If an event is specified, it removes all listeners for the specified event.
6setMaxListeners(n)
By default, EventEmitters output a warning if you add more than 10 listeners. The setMaxListeners function is used to change the default limit on the number of listeners.
7listeners(event)
Returns an array of listeners for the specified event.
8emit(event, [arg1], [arg2], [...])
Executes each listener in order. If the event has registered listeners, it returns true; otherwise, it returns false.

Class Methods

No.Method & Description
1listenerCount(emitter, event)
Returns the number of listeners for the specified event.
events.EventEmitter.listenerCount(emitter, eventName) //已废弃,不推荐
events.emitter.listenerCount(eventName) //推荐

Register an event listener:

Example

const EventEmitter = require('events');
const myEmitter = new EventEmitter();

// Register an event listener
myEmitter.on('sayHello', (name) => {
  console.log(`Hello, ${name}!`);
});

// Trigger event
myEmitter.emit('sayHello', 'Alice');

Output:

Hello, Alice!

Use once() to register a one-time event:

myEmitter.once('init', () => {
  console.log('Initialization event occurred');
});

myEmitter.emit('init'); // 打印: Initialization event occurred
myEmitter.emit('init'); // 不会再触发

Parameters can be passed when an event is triggered for use by the listeners:

Example


myEmitter.on('data', (value1, value2) => {
  console.log(`Received values: ${value1}, ${value2}`);
});

myEmitter.emit('data', 'Node.js', 'EventEmitter');
// Output: Received values: Node.js, EventEmitter

If the triggered event has no corresponding listener, EventEmitter will throw an error:

Example

myEmitter.on('error', (err) => {
  console.error('Error event triggered:', err);
});

myEmitter.emit('error', new Error('Something went wrong'));
// Print: Error event triggered: Error: Something went wrong

Events

No.Event & Description
1newListener
  • event- string, the event name

  • listener- function, the event handling function

This event is triggered when a new listener is added.

2removeListener
  • event- string, the event name

  • listener- function, the event handling function

Removes a listener from the specified listener array. Note that this operation will change the indices of the listeners that come after the removed listener.

Example

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

Create a main.js file with the following code:

Example

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

// Listener #1
var listener1 = function listener1() {
   console.log('Listener listener1 executed.');
}

// Listener #2
var listener2 = function listener2() {
  console.log('Listener listener2 executed.');
}

// Bind connection event, handler function is listener1
eventEmitter.addListener('connection', listener1);

// Bind connection event, handler function is listener2
eventEmitter.on('connection', listener2);

var eventListeners = eventEmitter.listenerCount('connection');
console.log(eventListeners + " listeners are listening to the connection event.");

// Handle connection event
eventEmitter.emit('connection');

// Remove the bound listener1 function
eventEmitter.removeListener('connection', listener1);
console.log("listener1 is no longer listening.");

// Trigger connection event
eventEmitter.emit('connection');

eventListeners = eventEmitter.listenerCount('connection');
console.log(eventListeners + " listeners are listening to the connection event.");

console.log("Program execution complete.");

The execution result of the above code is as follows:

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

error Event

EventEmitter defines a special event, error, which carries the semantics of an error. We usually trigger the error event when an exception occurs.

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

We generally set listeners for objects that may trigger the error event to prevent the whole program from crashing after an error occurs. For example:

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

The following error will be displayed at runtime:

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) 

Inheriting EventEmitter

Most of the time we do not use EventEmitter directly, but inherit it in objects. All core modules that support event responses, including fs, net, and http, are subclasses of EventEmitter.

Why do we do this? There are two reasons:

  • First, implementing events in an object with a certain concrete functionality is semantically appropriate; event listening and emitting should be methods of an object.

  • Second, JavaScript's object mechanism is prototype-based and supports partial multiple inheritance. Inheriting EventEmitter will not disturb the object's original inheritance relationship.

Most Node.js core modules (such as HTTP and the file system) inherit EventEmitter. You can create your own classes to inherit EventEmitter.

Example

class MyEmitter extends EventEmitter {}
const customEmitter = new MyEmitter();

customEmitter.on('customEvent', () => {
  console.log('Custom event fired');
});

customEmitter.emit('customEvent');
Other extensions