EventsAPI

interface EventsAPI : NodeAPI, ProxyObject

Node API: Events

Describes the surface of the events built-in module provided as part of the Node API; the events API provides types like EventEmitter, EventTarget, Event, and EventListener to work with events in Node.js.

Events in Node behave similarly to DOM (browser) events, with a few caveats.

For information about how the Node API behaves and how it differs from browsers, see the Node.js Events documentation.

Node Events

Much of the Node.js core API is built around an idiomatic asynchronous event-driven architecture in which certain kinds of objects (called "emitters") emit named events that cause Function objects ("listeners") to be called.

For instance: a net.Server object emits an event each time a peer connects to it; a fs.ReadStream emits an event when the file is opened; a stream emits an event whenever data is available to be read.

All objects that emit events are instances of the EventEmitter class. These objects expose an EventEmitter.on function that allows one or more functions to be attached to named events emitted by the object. Typically, event names are camel-cased strings but any valid JavaScript property key can be used.

When the EventEmitter object emits an event, all functions attached to that specific event are called synchronously. Any values returned by the called listeners are ignored and discarded.

The following example shows a simple EventEmitter instance with a single listener. The EventEmitter.on method is used to register listeners, while the EventEmitter.emit method is used to trigger the event:

import { EventEmitter } from 'node:events';

class MyEmitter extends EventEmitter {}

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

 

Passing arguments and this to listeners

The EventEmitter.emit method allows an arbitrary set of arguments to be passed to the listener functions. Keep in mind that when an ordinary listener function is called, the standard this keyword is intentionally set to reference the EventEmitter instance to which the listener is attached.

import { EventEmitter } from 'node:events';
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter();
myEmitter.on('event', function(a, b) {
console.log(a, b, this, this === myEmitter);
// Prints:
// a b MyEmitter {
// _events: [Object: null prototype] { event: [Function (anonymous)] },
// _eventsCount: 1,
// _maxListeners: undefined,
// [Symbol(shapeMode)]: false,
// [Symbol(kCapture)]: false
// } true
});
myEmitter.emit('event', 'a', 'b');

It is possible to use ES6 Arrow Functions as listeners, however, when doing so, the this keyword will no longer reference the EventEmitter instance:

import { EventEmitter } from 'node:events';
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter();
myEmitter.on('event', (a, b) => {
console.log(a, b, this);
// Prints: a b {}
});
myEmitter.emit('event', 'a', 'b');

 

Asynchronous vs. synchronous

The EventEmitter calls all listeners synchronously in the order in which they were registered. This ensures the proper sequencing of events and helps avoid race conditions and logic errors. When appropriate, listener functions can switch to an asynchronous mode of operation using the setImmediate() or process.nextTick() methods:

import { EventEmitter } from 'node:events';
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter();
myEmitter.on('event', (a, b) => {
setImmediate(() => {
console.log('this happens asynchronously');
});
});
myEmitter.emit('event', 'a', 'b');

 

Handling events only once

When a listener is registered using the EventEmitter.on method, that listener is invoked every time the named event is emitted.

import { EventEmitter } from 'node:events';
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter();
let m = 0;
myEmitter.on('event', () => {
console.log(++m);
});
myEmitter.emit('event');
// Prints: 1
myEmitter.emit('event');
// Prints: 2

Using the EventEmitter.once method, it is possible to register a listener which is called at most once for a particular event. Once the event is emitted, the listener is unregistered and then called.

import { EventEmitter } from 'node:events';
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter();
let m = 0;
myEmitter.once('event', () => {
console.log(++m);
});
myEmitter.emit('event');
// Prints: 1
myEmitter.emit('event');
// Ignored

 

Error events

When an error occurs within an EventEmitter instance, the typical action is for an 'error' event to be emitted. These are treated as special cases within Node.js.

If an EventEmitter does not have at least one listener registered for the 'error' event, and an 'error' event is emitted, the error is thrown, a stack trace is printed, and the Node.js process exits.

import { EventEmitter } from 'node:events';
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter();
myEmitter.emit('error', new Error('whoops!'));
// Throws and crashes Node.js

To guard against crashing the Node.js process the domain module can be used. (Note, however, that the node:domain module is deprecated.)

As a best practice, listeners should always be added for the 'error' events.

import { EventEmitter } from 'node:events';
class MyEmitter extends EventEmitter {}
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

It is possible to monitor 'error' events without consuming the emitted error by installing a listener using the symbol events.errorMonitor.

import { EventEmitter, errorMonitor } from 'node:events';

const myEmitter = new EventEmitter();
myEmitter.on(errorMonitor, (err) => {
MyMonitoringTool.log(err);
});
myEmitter.emit('error', new Error('whoops!'));
// Still throws and crashes Node.js

 

Capture rejections of promises

Using async functions with event handlers is problematic, because it can lead to an unhandled rejection in case of a thrown exception:

import { EventEmitter } from 'node:events';
const ee = new EventEmitter();
ee.on('something', async (value) => {
throw new Error('kaboom');
});

The captureRejections option in the EventEmitter constructor or the global setting change this behavior, installing a .then(undefined, handler) handler on the Promise. This handler routes the exception asynchronously to the Symbol.for('nodejs.rejection') method if there is one, or to 'error' event handler if there is none.

import { EventEmitter } from 'node:events';
const ee1 = new EventEmitter({ captureRejections: true });
ee1.on('something', async (value) => {
throw new Error('kaboom');
});

ee1.on('error', console.log);

const ee2 = new EventEmitter({ captureRejections: true });
ee2.on('something', async (value) => {
throw new Error('kaboom');
});

ee2[Symbol.for('nodejs.rejection')] = console.log;

Setting events.captureRejections = true will change the default for all new instances of EventEmitter.

import { EventEmitter } from 'node:events';

EventEmitter.captureRejections = true;
const ee1 = new EventEmitter();
ee1.on('something', async (value) => {
throw new Error('kaboom');
});

ee1.on('error', console.log);

The 'error' events that are generated by the captureRejections behavior do not have a catch handler to avoid infinite error loops: the recommendation is to not use async functions as 'error' event handlers.

See also

for the base class for all events

for the extension point used to create custom event types

for the interface supported for targets, or subjects, of events

for the interface supported for objects that emit events

Properties

Link copied to clipboard

If set to true, the 'rejectionHandled' event is emitted whenever a Promise is rejected, but there are no listeners to handle the rejection. This event is emitted with the following arguments:

Link copied to clipboard
abstract var defaultMaxListeners: Int

By default, a maximum of 10 listeners can be registered for any single event. This limit can be changed for individual EventEmitter instances using the emitter.setMaxListeners(n) method. To change the default for all EventEmitter instances, the events.defaultMaxListeners property can be used. If this value is not a positive number, a RangeError is thrown.

Link copied to clipboard
abstract var errorMonitor: Any?

This symbol shall be used to install a listener for only monitoring 'error' events. Listeners installed using this symbol are called before the regular 'error' listeners are called.

Functions

Link copied to clipboard
abstract fun addAbortListener(signal: AbortSignal, listener: EventListener): Disposable

Listens once to the abort event on the provided signal.

Link copied to clipboard
abstract fun getEventListeners(emitterOrTarget: EmitterOrTarget, event: String): List<EventListener>

Returns an array listing the events for which the emitter has registered listeners. The values in the array are strings or Symbols.

Link copied to clipboard
abstract fun getMaxListeners(emitterOrTarget: EmitterOrTarget): Int

Returns the current max listener value for the given emitter or target.

Link copied to clipboard
abstract fun getMember(key: String): Any
Link copied to clipboard
open override fun getMemberKeys(): Array<String>
Link copied to clipboard
open override fun hasMember(key: String): Boolean
Link copied to clipboard
abstract fun listenerCount(emitter: EventEmitterOrTarget, eventName: String): Int

Returns the number of listeners listening to the event named eventName.

abstract fun listenerCount(emitter: Value, event: String): Int

Returns the number of listeners listening to the event named event.

Link copied to clipboard
abstract fun on(emitter: EventEmitter, name: String)
abstract fun on(emitter: EventEmitter, name: String, options: EventsOnceOptions)
abstract fun on(emitter: EventEmitter, name: String, options: Value)

Adds the listener function to the end of the listeners array for the event named name to the emitter.

Link copied to clipboard
abstract fun once(emitter: EventEmitter, name: String): JsPromise<Unit>
abstract fun once(emitter: EventEmitter, name: String, options: EventsOnceOptions): JsPromise<Unit>
abstract fun once(emitter: EventEmitter, name: String, options: Value): JsPromise<Unit>

Adds a one-time listener function for the event named name to the emitter. The next time name is triggered, this listener is removed and then invoked.

Link copied to clipboard
open override fun putMember(key: String?, value: Value?)
Link copied to clipboard
open override fun removeMember(key: String?): Boolean
Link copied to clipboard
abstract fun setMaxListeners(count: Int, vararg emittersOrTargets: EmitterOrTarget)

Sets the maximum number of listeners for the given emitter or target.