Static
Readonly
captureStatic
captureValue: boolean
+Change the default captureRejections
option on all new EventEmitter
objects.
Static
defaultBy 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 allEventEmitter
instances, the events.defaultMaxListeners
property
+can be used. If this value is not a positive number, a RangeError
is thrown.
Take caution when setting the events.defaultMaxListeners
because the
+change affects all EventEmitter
instances, including those created before
+the change is made. However, calling emitter.setMaxListeners(n)
still has
+precedence over events.defaultMaxListeners
.
This is not a hard limit. The EventEmitter
instance will allow
+more listeners to be added but will output a trace warning to stderr indicating
+that a "possible EventEmitter memory leak" has been detected. For any single
+EventEmitter
, the emitter.getMaxListeners()
and emitter.setMaxListeners()
methods can be used to
+temporarily avoid this warning:
import { EventEmitter } from 'node:events';
const emitter = new EventEmitter();
emitter.setMaxListeners(emitter.getMaxListeners() + 1);
emitter.once('event', () => {
// do stuff
emitter.setMaxListeners(Math.max(emitter.getMaxListeners() - 1, 0));
});
+
+
+The --trace-warnings
command-line flag can be used to display the
+stack trace for such warnings.
The emitted warning can be inspected with process.on('warning')
and will
+have the additional emitter
, type
, and count
properties, referring to
+the event emitter instance, the event's name and the number of attached
+listeners, respectively.
+Its name
property is set to 'MaxListenersExceededWarning'
.
Static
Readonly
errorThis 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.
Installing a listener using this symbol does not change the behavior once an 'error'
event is emitted. Therefore, the process will still crash if no
+regular 'error'
listener is installed.
Optional
[captureRest
...args: AnyRestAlias for emitter.on(eventName, listener)
.
Rest
...args: any[]Synchronously calls each of the listeners registered for the event named eventName
, in the order they were registered, passing the supplied arguments
+to each.
Returns true
if the event had listeners, false
otherwise.
import { EventEmitter } from 'node:events';
const myEmitter = new EventEmitter();
// First listener
myEmitter.on('event', function firstListener() {
console.log('Helloooo! first listener');
});
// Second listener
myEmitter.on('event', function secondListener(arg1, arg2) {
console.log(`event with parameters ${arg1}, ${arg2} in second listener`);
});
// Third listener
myEmitter.on('event', function thirdListener(...args) {
const parameters = args.join(', ');
console.log(`event with parameters ${parameters} in third listener`);
});
console.log(myEmitter.listeners('event'));
myEmitter.emit('event', 1, 2, 3, 4, 5);
// Prints:
// [
// [Function: firstListener],
// [Function: secondListener],
// [Function: thirdListener]
// ]
// Helloooo! first listener
// event with parameters 1, 2 in second listener
// event with parameters 1, 2, 3, 4, 5 in third listener
+
+
+Rest
...args: AnyRestReturns an array listing the events for which the emitter has registered
+listeners. The values in the array are strings or Symbol
s.
import { EventEmitter } from 'node:events';
const myEE = new EventEmitter();
myEE.on('foo', () => {});
myEE.on('bar', () => {});
const sym = Symbol('symbol');
myEE.on(sym, () => {});
console.log(myEE.eventNames());
// Prints: [ 'foo', 'bar', Symbol(symbol) ]
+
+
+Returns the current max listener value for the EventEmitter
which is either
+set by emitter.setMaxListeners(n)
or defaults to defaultMaxListeners.
Returns the number of listeners listening for the event named eventName
.
+If listener
is provided, it will return how many times the listener is found
+in the list of the listeners of the event.
The name of the event being listened for
+Optional
listener: FunctionThe event handler function
+Returns a copy of the array of listeners for the event named eventName
.
server.on('connection', (stream) => {
console.log('someone connected!');
});
console.log(util.inspect(server.listeners('connection')));
// Prints: [ [Function] ]
+
+
+Alias for emitter.removeListener()
.
Rest
...args: any[]Adds the listener
function to the end of the listeners array for the event
+named eventName
. No checks are made to see if the listener
has already
+been added. Multiple calls passing the same combination of eventName
and
+listener
will result in the listener
being added, and called, multiple times.
server.on('connection', (stream) => {
console.log('someone connected!');
});
+
+
+Returns a reference to the EventEmitter
, so that calls can be chained.
By default, event listeners are invoked in the order they are added. The emitter.prependListener()
method can be used as an alternative to add the
+event listener to the beginning of the listeners array.
import { EventEmitter } from 'node:events';
const myEE = new EventEmitter();
myEE.on('foo', () => console.log('a'));
myEE.prependListener('foo', () => console.log('b'));
myEE.emit('foo');
// Prints:
// b
// a
+
+
+The name of the event.
+The callback function
+Rest
...args: any[]Adds a one-time listener
function for the event named eventName
. The
+next time eventName
is triggered, this listener is removed and then invoked.
server.once('connection', (stream) => {
console.log('Ah, we have our first user!');
});
+
+
+Returns a reference to the EventEmitter
, so that calls can be chained.
By default, event listeners are invoked in the order they are added. The emitter.prependOnceListener()
method can be used as an alternative to add the
+event listener to the beginning of the listeners array.
import { EventEmitter } from 'node:events';
const myEE = new EventEmitter();
myEE.once('foo', () => console.log('a'));
myEE.prependOnceListener('foo', () => console.log('b'));
myEE.emit('foo');
// Prints:
// b
// a
+
+
+The name of the event.
+The callback function
+Rest
...args: any[]Adds the listener
function to the beginning of the listeners array for the
+event named eventName
. No checks are made to see if the listener
has
+already been added. Multiple calls passing the same combination of eventName
+and listener
will result in the listener
being added, and called, multiple times.
server.prependListener('connection', (stream) => {
console.log('someone connected!');
});
+
+
+Returns a reference to the EventEmitter
, so that calls can be chained.
The name of the event.
+The callback function
+Rest
...args: any[]Adds a one-timelistener
function for the event named eventName
to the beginning of the listeners array. The next time eventName
is triggered, this
+listener is removed, and then invoked.
server.prependOnceListener('connection', (stream) => {
console.log('Ah, we have our first user!');
});
+
+
+Returns a reference to the EventEmitter
, so that calls can be chained.
The name of the event.
+The callback function
+Rest
...args: any[]Returns a copy of the array of listeners for the event named eventName
,
+including any wrappers (such as those created by .once()
).
import { EventEmitter } from 'node:events';
const emitter = new EventEmitter();
emitter.once('log', () => console.log('log once'));
// Returns a new Array with a function `onceWrapper` which has a property
// `listener` which contains the original listener bound above
const listeners = emitter.rawListeners('log');
const logFnWrapper = listeners[0];
// Logs "log once" to the console and does not unbind the `once` event
logFnWrapper.listener();
// Logs "log once" to the console and removes the listener
logFnWrapper();
emitter.on('log', () => console.log('log persistently'));
// Will return a new Array with a single function bound by `.on()` above
const newListeners = emitter.rawListeners('log');
// Logs "log persistently" twice
newListeners[0]();
emitter.emit('log');
+
+
+Removes all listeners, or those of the specified eventName
.
It is bad practice to remove listeners added elsewhere in the code,
+particularly when the EventEmitter
instance was created by some other
+component or module (e.g. sockets or file streams).
Returns a reference to the EventEmitter
, so that calls can be chained.
Optional
eventName: string | symbolRemoves the specified listener
from the listener array for the event named eventName
.
const callback = (stream) => {
console.log('someone connected!');
};
server.on('connection', callback);
// ...
server.removeListener('connection', callback);
+
+
+removeListener()
will remove, at most, one instance of a listener from the
+listener array. If any single listener has been added multiple times to the
+listener array for the specified eventName
, then removeListener()
must be
+called multiple times to remove each instance.
Once an event is emitted, all listeners attached to it at the
+time of emitting are called in order. This implies that any removeListener()
or removeAllListeners()
calls after emitting and before the last listener finishes execution
+will not remove them fromemit()
in progress. Subsequent events behave as expected.
import { EventEmitter } from 'node:events';
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter();
const callbackA = () => {
console.log('A');
myEmitter.removeListener('event', callbackB);
};
const callbackB = () => {
console.log('B');
};
myEmitter.on('event', callbackA);
myEmitter.on('event', callbackB);
// callbackA removes listener callbackB but it will still be called.
// Internal listener array at time of emit [callbackA, callbackB]
myEmitter.emit('event');
// Prints:
// A
// B
// callbackB is now removed.
// Internal listener array [callbackA]
myEmitter.emit('event');
// Prints:
// A
+
+
+Because listeners are managed using an internal array, calling this will
+change the position indices of any listener registered after the listener
+being removed. This will not impact the order in which listeners are called,
+but it means that any copies of the listener array as returned by
+the emitter.listeners()
method will need to be recreated.
When a single function has been added as a handler multiple times for a single
+event (as in the example below), removeListener()
will remove the most
+recently added instance. In the example the once('ping')
listener is removed:
import { EventEmitter } from 'node:events';
const ee = new EventEmitter();
function pong() {
console.log('pong');
}
ee.on('ping', pong);
ee.once('ping', pong);
ee.removeListener('ping', pong);
ee.emit('ping');
ee.emit('ping');
+
+
+Returns a reference to the EventEmitter
, so that calls can be chained.
Rest
...args: any[]By default EventEmitter
s will print a warning if more than 10
listeners are
+added for a particular event. This is a useful default that helps finding
+memory leaks. The emitter.setMaxListeners()
method allows the limit to be
+modified for this specific EventEmitter
instance. The value can be set to Infinity
(or 0
) to indicate an unlimited number of listeners.
Returns a reference to the EventEmitter
, so that calls can be chained.
Static
addExperimental
Listens once to the abort
event on the provided signal
.
Listening to the abort
event on abort signals is unsafe and may
+lead to resource leaks since another third party with the signal can
+call e.stopImmediatePropagation()
. Unfortunately Node.js cannot change
+this since it would violate the web standard. Additionally, the original
+API makes it easy to forget to remove listeners.
This API allows safely using AbortSignal
s in Node.js APIs by solving these
+two issues by listening to the event such that stopImmediatePropagation
does
+not prevent the listener from running.
Returns a disposable so that it may be unsubscribed from more easily.
+import { addAbortListener } from 'node:events';
function example(signal) {
let disposable;
try {
signal.addEventListener('abort', (e) => e.stopImmediatePropagation());
disposable = addAbortListener(signal, (e) => {
// Do something when signal is aborted.
});
} finally {
disposable?.[Symbol.dispose]();
}
}
+
+
+Disposable that removes the abort
listener.
Static
getReturns a copy of the array of listeners for the event named eventName
.
For EventEmitter
s this behaves exactly the same as calling .listeners
on
+the emitter.
For EventTarget
s this is the only way to get the event listeners for the
+event target. This is useful for debugging and diagnostic purposes.
import { getEventListeners, EventEmitter } from 'node:events';
{
const ee = new EventEmitter();
const listener = () => console.log('Events are fun');
ee.on('foo', listener);
console.log(getEventListeners(ee, 'foo')); // [ [Function: listener] ]
}
{
const et = new EventTarget();
const listener = () => console.log('Events are fun');
et.addEventListener('foo', listener);
console.log(getEventListeners(et, 'foo')); // [ [Function: listener] ]
}
+
+
+Static
getReturns the currently set max amount of listeners.
+For EventEmitter
s this behaves exactly the same as calling .getMaxListeners
on
+the emitter.
For EventTarget
s this is the only way to get the max event listeners for the
+event target. If the number of event handlers on a single EventTarget exceeds
+the max set, the EventTarget will print a warning.
import { getMaxListeners, setMaxListeners, EventEmitter } from 'node:events';
{
const ee = new EventEmitter();
console.log(getMaxListeners(ee)); // 10
setMaxListeners(11, ee);
console.log(getMaxListeners(ee)); // 11
}
{
const et = new EventTarget();
console.log(getMaxListeners(et)); // 10
setMaxListeners(11, et);
console.log(getMaxListeners(et)); // 11
}
+
+
+Static
listenerA class method that returns the number of listeners for the given eventName
registered on the given emitter
.
import { EventEmitter, listenerCount } from 'node:events';
const myEmitter = new EventEmitter();
myEmitter.on('event', () => {});
myEmitter.on('event', () => {});
console.log(listenerCount(myEmitter, 'event'));
// Prints: 2
+
+
+The emitter to query
+The event name
+Static
onimport { on, EventEmitter } from 'node:events';
import process from 'node:process';
const ee = new EventEmitter();
// Emit later on
process.nextTick(() => {
ee.emit('foo', 'bar');
ee.emit('foo', 42);
});
for await (const event of on(ee, 'foo')) {
// The execution of this inner block is synchronous and it
// processes one event at a time (even with await). Do not use
// if concurrent execution is required.
console.log(event); // prints ['bar'] [42]
}
// Unreachable here
+
+
+Returns an AsyncIterator
that iterates eventName
events. It will throw
+if the EventEmitter
emits 'error'
. It removes all listeners when
+exiting the loop. The value
returned by each iteration is an array
+composed of the emitted event arguments.
An AbortSignal
can be used to cancel waiting on events:
import { on, EventEmitter } from 'node:events';
import process from 'node:process';
const ac = new AbortController();
(async () => {
const ee = new EventEmitter();
// Emit later on
process.nextTick(() => {
ee.emit('foo', 'bar');
ee.emit('foo', 42);
});
for await (const event of on(ee, 'foo', { signal: ac.signal })) {
// The execution of this inner block is synchronous and it
// processes one event at a time (even with await). Do not use
// if concurrent execution is required.
console.log(event); // prints ['bar'] [42]
}
// Unreachable here
})();
process.nextTick(() => ac.abort());
+
+
+Use the close
option to specify an array of event names that will end the iteration:
import { on, EventEmitter } from 'node:events';
import process from 'node:process';
const ee = new EventEmitter();
// Emit later on
process.nextTick(() => {
ee.emit('foo', 'bar');
ee.emit('foo', 42);
ee.emit('close');
});
for await (const event of on(ee, 'foo', { close: ['close'] })) {
console.log(event); // prints ['bar'] [42]
}
// the loop will exit after 'close' is emitted
console.log('done'); // prints 'done'
+
+
+Optional
options: StaticEventEmitterIteratorOptionsAn AsyncIterator
that iterates eventName
events emitted by the emitter
Optional
options: StaticEventEmitterIteratorOptionsStatic
onceCreates a Promise
that is fulfilled when the EventEmitter
emits the given
+event or that is rejected if the EventEmitter
emits 'error'
while waiting.
+The Promise
will resolve with an array of all the arguments emitted to the
+given event.
This method is intentionally generic and works with the web platform EventTarget interface, which has no special'error'
event
+semantics and does not listen to the 'error'
event.
import { once, EventEmitter } from 'node:events';
import process from 'node:process';
const ee = new EventEmitter();
process.nextTick(() => {
ee.emit('myevent', 42);
});
const [value] = await once(ee, 'myevent');
console.log(value);
const err = new Error('kaboom');
process.nextTick(() => {
ee.emit('error', err);
});
try {
await once(ee, 'myevent');
} catch (err) {
console.error('error happened', err);
}
+
+
+The special handling of the 'error'
event is only used when events.once()
is used to wait for another event. If events.once()
is used to wait for the
+'error'
event itself, then it is treated as any other kind of event without
+special handling:
import { EventEmitter, once } from 'node:events';
const ee = new EventEmitter();
once(ee, 'error')
.then(([err]) => console.log('ok', err.message))
.catch((err) => console.error('error', err.message));
ee.emit('error', new Error('boom'));
// Prints: ok boom
+
+
+An AbortSignal
can be used to cancel waiting for the event:
import { EventEmitter, once } from 'node:events';
const ee = new EventEmitter();
const ac = new AbortController();
async function foo(emitter, event, signal) {
try {
await once(emitter, event, { signal });
console.log('event emitted!');
} catch (error) {
if (error.name === 'AbortError') {
console.error('Waiting for the event was canceled!');
} else {
console.error('There was an error', error.message);
}
}
}
foo(ee, 'foo', ac.signal);
ac.abort(); // Abort waiting for the event
ee.emit('foo'); // Prints: Waiting for the event was canceled!
+
+
+Optional
options: StaticEventEmitterOptionsOptional
options: StaticEventEmitterOptionsStatic
setimport { setMaxListeners, EventEmitter } from 'node:events';
const target = new EventTarget();
const emitter = new EventEmitter();
setMaxListeners(5, target, emitter);
+
+
+Optional
n: numberA non-negative number. The maximum number of listeners per EventTarget
event.
Rest
...eventTargets: (EventTarget | EventEmitter<DefaultEventMap>)[]Static
Readonly
captureValue: Symbol.for('nodejs.rejection')
See how to write a custom rejection handler
.
Static
captureValue: boolean
+Change the default captureRejections
option on all new EventEmitter
objects.
Static
defaultBy 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 allEventEmitter
instances, the events.defaultMaxListeners
property
+can be used. If this value is not a positive number, a RangeError
is thrown.
Take caution when setting the events.defaultMaxListeners
because the
+change affects all EventEmitter
instances, including those created before
+the change is made. However, calling emitter.setMaxListeners(n)
still has
+precedence over events.defaultMaxListeners
.
This is not a hard limit. The EventEmitter
instance will allow
+more listeners to be added but will output a trace warning to stderr indicating
+that a "possible EventEmitter memory leak" has been detected. For any single
+EventEmitter
, the emitter.getMaxListeners()
and emitter.setMaxListeners()
methods can be used to
+temporarily avoid this warning:
import { EventEmitter } from 'node:events';
const emitter = new EventEmitter();
emitter.setMaxListeners(emitter.getMaxListeners() + 1);
emitter.once('event', () => {
// do stuff
emitter.setMaxListeners(Math.max(emitter.getMaxListeners() - 1, 0));
});
+
+
+The --trace-warnings
command-line flag can be used to display the
+stack trace for such warnings.
The emitted warning can be inspected with process.on('warning')
and will
+have the additional emitter
, type
, and count
properties, referring to
+the event emitter instance, the event's name and the number of attached
+listeners, respectively.
+Its name
property is set to 'MaxListenersExceededWarning'
.
Static
Readonly
errorThis 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.
Installing a listener using this symbol does not change the behavior once an 'error'
event is emitted. Therefore, the process will still crash if no
+regular 'error'
listener is installed.
Optional
[captureRest
...args: AnyRestAlias for emitter.on(eventName, listener)
.
Rest
...args: any[]Synchronously calls each of the listeners registered for the event named eventName
, in the order they were registered, passing the supplied arguments
+to each.
Returns true
if the event had listeners, false
otherwise.
import { EventEmitter } from 'node:events';
const myEmitter = new EventEmitter();
// First listener
myEmitter.on('event', function firstListener() {
console.log('Helloooo! first listener');
});
// Second listener
myEmitter.on('event', function secondListener(arg1, arg2) {
console.log(`event with parameters ${arg1}, ${arg2} in second listener`);
});
// Third listener
myEmitter.on('event', function thirdListener(...args) {
const parameters = args.join(', ');
console.log(`event with parameters ${parameters} in third listener`);
});
console.log(myEmitter.listeners('event'));
myEmitter.emit('event', 1, 2, 3, 4, 5);
// Prints:
// [
// [Function: firstListener],
// [Function: secondListener],
// [Function: thirdListener]
// ]
// Helloooo! first listener
// event with parameters 1, 2 in second listener
// event with parameters 1, 2, 3, 4, 5 in third listener
+
+
+Rest
...args: AnyRestReturns an array listing the events for which the emitter has registered
+listeners. The values in the array are strings or Symbol
s.
import { EventEmitter } from 'node:events';
const myEE = new EventEmitter();
myEE.on('foo', () => {});
myEE.on('bar', () => {});
const sym = Symbol('symbol');
myEE.on(sym, () => {});
console.log(myEE.eventNames());
// Prints: [ 'foo', 'bar', Symbol(symbol) ]
+
+
+Returns the current max listener value for the EventEmitter
which is either
+set by emitter.setMaxListeners(n)
or defaults to defaultMaxListeners.
Returns the number of listeners listening for the event named eventName
.
+If listener
is provided, it will return how many times the listener is found
+in the list of the listeners of the event.
The name of the event being listened for
+Optional
listener: FunctionThe event handler function
+Returns a copy of the array of listeners for the event named eventName
.
server.on('connection', (stream) => {
console.log('someone connected!');
});
console.log(util.inspect(server.listeners('connection')));
// Prints: [ [Function] ]
+
+
+Alias for emitter.removeListener()
.
Rest
...args: any[]Adds a one-time listener
function for the event named eventName
. The
+next time eventName
is triggered, this listener is removed and then invoked.
server.once('connection', (stream) => {
console.log('Ah, we have our first user!');
});
+
+
+Returns a reference to the EventEmitter
, so that calls can be chained.
By default, event listeners are invoked in the order they are added. The emitter.prependOnceListener()
method can be used as an alternative to add the
+event listener to the beginning of the listeners array.
import { EventEmitter } from 'node:events';
const myEE = new EventEmitter();
myEE.once('foo', () => console.log('a'));
myEE.prependOnceListener('foo', () => console.log('b'));
myEE.emit('foo');
// Prints:
// b
// a
+
+
+The name of the event.
+The callback function
+Rest
...args: any[]Adds the listener
function to the beginning of the listeners array for the
+event named eventName
. No checks are made to see if the listener
has
+already been added. Multiple calls passing the same combination of eventName
+and listener
will result in the listener
being added, and called, multiple times.
server.prependListener('connection', (stream) => {
console.log('someone connected!');
});
+
+
+Returns a reference to the EventEmitter
, so that calls can be chained.
The name of the event.
+The callback function
+Rest
...args: any[]Adds a one-timelistener
function for the event named eventName
to the beginning of the listeners array. The next time eventName
is triggered, this
+listener is removed, and then invoked.
server.prependOnceListener('connection', (stream) => {
console.log('Ah, we have our first user!');
});
+
+
+Returns a reference to the EventEmitter
, so that calls can be chained.
The name of the event.
+The callback function
+Rest
...args: any[]Returns a copy of the array of listeners for the event named eventName
,
+including any wrappers (such as those created by .once()
).
import { EventEmitter } from 'node:events';
const emitter = new EventEmitter();
emitter.once('log', () => console.log('log once'));
// Returns a new Array with a function `onceWrapper` which has a property
// `listener` which contains the original listener bound above
const listeners = emitter.rawListeners('log');
const logFnWrapper = listeners[0];
// Logs "log once" to the console and does not unbind the `once` event
logFnWrapper.listener();
// Logs "log once" to the console and removes the listener
logFnWrapper();
emitter.on('log', () => console.log('log persistently'));
// Will return a new Array with a single function bound by `.on()` above
const newListeners = emitter.rawListeners('log');
// Logs "log persistently" twice
newListeners[0]();
emitter.emit('log');
+
+
+Removes all listeners, or those of the specified eventName
.
It is bad practice to remove listeners added elsewhere in the code,
+particularly when the EventEmitter
instance was created by some other
+component or module (e.g. sockets or file streams).
Returns a reference to the EventEmitter
, so that calls can be chained.
Optional
eventName: string | symbolRemoves the specified listener
from the listener array for the event named eventName
.
const callback = (stream) => {
console.log('someone connected!');
};
server.on('connection', callback);
// ...
server.removeListener('connection', callback);
+
+
+removeListener()
will remove, at most, one instance of a listener from the
+listener array. If any single listener has been added multiple times to the
+listener array for the specified eventName
, then removeListener()
must be
+called multiple times to remove each instance.
Once an event is emitted, all listeners attached to it at the
+time of emitting are called in order. This implies that any removeListener()
or removeAllListeners()
calls after emitting and before the last listener finishes execution
+will not remove them fromemit()
in progress. Subsequent events behave as expected.
import { EventEmitter } from 'node:events';
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter();
const callbackA = () => {
console.log('A');
myEmitter.removeListener('event', callbackB);
};
const callbackB = () => {
console.log('B');
};
myEmitter.on('event', callbackA);
myEmitter.on('event', callbackB);
// callbackA removes listener callbackB but it will still be called.
// Internal listener array at time of emit [callbackA, callbackB]
myEmitter.emit('event');
// Prints:
// A
// B
// callbackB is now removed.
// Internal listener array [callbackA]
myEmitter.emit('event');
// Prints:
// A
+
+
+Because listeners are managed using an internal array, calling this will
+change the position indices of any listener registered after the listener
+being removed. This will not impact the order in which listeners are called,
+but it means that any copies of the listener array as returned by
+the emitter.listeners()
method will need to be recreated.
When a single function has been added as a handler multiple times for a single
+event (as in the example below), removeListener()
will remove the most
+recently added instance. In the example the once('ping')
listener is removed:
import { EventEmitter } from 'node:events';
const ee = new EventEmitter();
function pong() {
console.log('pong');
}
ee.on('ping', pong);
ee.once('ping', pong);
ee.removeListener('ping', pong);
ee.emit('ping');
ee.emit('ping');
+
+
+Returns a reference to the EventEmitter
, so that calls can be chained.
Rest
...args: any[]By default EventEmitter
s will print a warning if more than 10
listeners are
+added for a particular event. This is a useful default that helps finding
+memory leaks. The emitter.setMaxListeners()
method allows the limit to be
+modified for this specific EventEmitter
instance. The value can be set to Infinity
(or 0
) to indicate an unlimited number of listeners.
Returns a reference to the EventEmitter
, so that calls can be chained.
Static
addExperimental
Listens once to the abort
event on the provided signal
.
Listening to the abort
event on abort signals is unsafe and may
+lead to resource leaks since another third party with the signal can
+call e.stopImmediatePropagation()
. Unfortunately Node.js cannot change
+this since it would violate the web standard. Additionally, the original
+API makes it easy to forget to remove listeners.
This API allows safely using AbortSignal
s in Node.js APIs by solving these
+two issues by listening to the event such that stopImmediatePropagation
does
+not prevent the listener from running.
Returns a disposable so that it may be unsubscribed from more easily.
+import { addAbortListener } from 'node:events';
function example(signal) {
let disposable;
try {
signal.addEventListener('abort', (e) => e.stopImmediatePropagation());
disposable = addAbortListener(signal, (e) => {
// Do something when signal is aborted.
});
} finally {
disposable?.[Symbol.dispose]();
}
}
+
+
+Disposable that removes the abort
listener.
Static
getReturns a copy of the array of listeners for the event named eventName
.
For EventEmitter
s this behaves exactly the same as calling .listeners
on
+the emitter.
For EventTarget
s this is the only way to get the event listeners for the
+event target. This is useful for debugging and diagnostic purposes.
import { getEventListeners, EventEmitter } from 'node:events';
{
const ee = new EventEmitter();
const listener = () => console.log('Events are fun');
ee.on('foo', listener);
console.log(getEventListeners(ee, 'foo')); // [ [Function: listener] ]
}
{
const et = new EventTarget();
const listener = () => console.log('Events are fun');
et.addEventListener('foo', listener);
console.log(getEventListeners(et, 'foo')); // [ [Function: listener] ]
}
+
+
+Static
getReturns the currently set max amount of listeners.
+For EventEmitter
s this behaves exactly the same as calling .getMaxListeners
on
+the emitter.
For EventTarget
s this is the only way to get the max event listeners for the
+event target. If the number of event handlers on a single EventTarget exceeds
+the max set, the EventTarget will print a warning.
import { getMaxListeners, setMaxListeners, EventEmitter } from 'node:events';
{
const ee = new EventEmitter();
console.log(getMaxListeners(ee)); // 10
setMaxListeners(11, ee);
console.log(getMaxListeners(ee)); // 11
}
{
const et = new EventTarget();
console.log(getMaxListeners(et)); // 10
setMaxListeners(11, et);
console.log(getMaxListeners(et)); // 11
}
+
+
+Static
listenerA class method that returns the number of listeners for the given eventName
registered on the given emitter
.
import { EventEmitter, listenerCount } from 'node:events';
const myEmitter = new EventEmitter();
myEmitter.on('event', () => {});
myEmitter.on('event', () => {});
console.log(listenerCount(myEmitter, 'event'));
// Prints: 2
+
+
+The emitter to query
+The event name
+Static
onimport { on, EventEmitter } from 'node:events';
import process from 'node:process';
const ee = new EventEmitter();
// Emit later on
process.nextTick(() => {
ee.emit('foo', 'bar');
ee.emit('foo', 42);
});
for await (const event of on(ee, 'foo')) {
// The execution of this inner block is synchronous and it
// processes one event at a time (even with await). Do not use
// if concurrent execution is required.
console.log(event); // prints ['bar'] [42]
}
// Unreachable here
+
+
+Returns an AsyncIterator
that iterates eventName
events. It will throw
+if the EventEmitter
emits 'error'
. It removes all listeners when
+exiting the loop. The value
returned by each iteration is an array
+composed of the emitted event arguments.
An AbortSignal
can be used to cancel waiting on events:
import { on, EventEmitter } from 'node:events';
import process from 'node:process';
const ac = new AbortController();
(async () => {
const ee = new EventEmitter();
// Emit later on
process.nextTick(() => {
ee.emit('foo', 'bar');
ee.emit('foo', 42);
});
for await (const event of on(ee, 'foo', { signal: ac.signal })) {
// The execution of this inner block is synchronous and it
// processes one event at a time (even with await). Do not use
// if concurrent execution is required.
console.log(event); // prints ['bar'] [42]
}
// Unreachable here
})();
process.nextTick(() => ac.abort());
+
+
+Use the close
option to specify an array of event names that will end the iteration:
import { on, EventEmitter } from 'node:events';
import process from 'node:process';
const ee = new EventEmitter();
// Emit later on
process.nextTick(() => {
ee.emit('foo', 'bar');
ee.emit('foo', 42);
ee.emit('close');
});
for await (const event of on(ee, 'foo', { close: ['close'] })) {
console.log(event); // prints ['bar'] [42]
}
// the loop will exit after 'close' is emitted
console.log('done'); // prints 'done'
+
+
+Optional
options: StaticEventEmitterIteratorOptionsAn AsyncIterator
that iterates eventName
events emitted by the emitter
Optional
options: StaticEventEmitterIteratorOptionsStatic
onceCreates a Promise
that is fulfilled when the EventEmitter
emits the given
+event or that is rejected if the EventEmitter
emits 'error'
while waiting.
+The Promise
will resolve with an array of all the arguments emitted to the
+given event.
This method is intentionally generic and works with the web platform EventTarget interface, which has no special'error'
event
+semantics and does not listen to the 'error'
event.
import { once, EventEmitter } from 'node:events';
import process from 'node:process';
const ee = new EventEmitter();
process.nextTick(() => {
ee.emit('myevent', 42);
});
const [value] = await once(ee, 'myevent');
console.log(value);
const err = new Error('kaboom');
process.nextTick(() => {
ee.emit('error', err);
});
try {
await once(ee, 'myevent');
} catch (err) {
console.error('error happened', err);
}
+
+
+The special handling of the 'error'
event is only used when events.once()
is used to wait for another event. If events.once()
is used to wait for the
+'error'
event itself, then it is treated as any other kind of event without
+special handling:
import { EventEmitter, once } from 'node:events';
const ee = new EventEmitter();
once(ee, 'error')
.then(([err]) => console.log('ok', err.message))
.catch((err) => console.error('error', err.message));
ee.emit('error', new Error('boom'));
// Prints: ok boom
+
+
+An AbortSignal
can be used to cancel waiting for the event:
import { EventEmitter, once } from 'node:events';
const ee = new EventEmitter();
const ac = new AbortController();
async function foo(emitter, event, signal) {
try {
await once(emitter, event, { signal });
console.log('event emitted!');
} catch (error) {
if (error.name === 'AbortError') {
console.error('Waiting for the event was canceled!');
} else {
console.error('There was an error', error.message);
}
}
}
foo(ee, 'foo', ac.signal);
ac.abort(); // Abort waiting for the event
ee.emit('foo'); // Prints: Waiting for the event was canceled!
+
+
+Optional
options: StaticEventEmitterOptionsOptional
options: StaticEventEmitterOptionsStatic
setimport { setMaxListeners, EventEmitter } from 'node:events';
const target = new EventTarget();
const emitter = new EventEmitter();
setMaxListeners(5, target, emitter);
+
+
+Optional
n: numberA non-negative number. The maximum number of listeners per EventTarget
event.
Rest
...eventTargets: (EventTarget | EventEmitter<DefaultEventMap>)[]Abstract
Static
Readonly
captureValue: Symbol.for('nodejs.rejection')
See how to write a custom rejection handler
.
Static
captureValue: boolean
+Change the default captureRejections
option on all new EventEmitter
objects.
Static
defaultBy 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 allEventEmitter
instances, the events.defaultMaxListeners
property
+can be used. If this value is not a positive number, a RangeError
is thrown.
Take caution when setting the events.defaultMaxListeners
because the
+change affects all EventEmitter
instances, including those created before
+the change is made. However, calling emitter.setMaxListeners(n)
still has
+precedence over events.defaultMaxListeners
.
This is not a hard limit. The EventEmitter
instance will allow
+more listeners to be added but will output a trace warning to stderr indicating
+that a "possible EventEmitter memory leak" has been detected. For any single
+EventEmitter
, the emitter.getMaxListeners()
and emitter.setMaxListeners()
methods can be used to
+temporarily avoid this warning:
import { EventEmitter } from 'node:events';
const emitter = new EventEmitter();
emitter.setMaxListeners(emitter.getMaxListeners() + 1);
emitter.once('event', () => {
// do stuff
emitter.setMaxListeners(Math.max(emitter.getMaxListeners() - 1, 0));
});
+
+
+The --trace-warnings
command-line flag can be used to display the
+stack trace for such warnings.
The emitted warning can be inspected with process.on('warning')
and will
+have the additional emitter
, type
, and count
properties, referring to
+the event emitter instance, the event's name and the number of attached
+listeners, respectively.
+Its name
property is set to 'MaxListenersExceededWarning'
.
Static
Readonly
errorThis 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.
Installing a listener using this symbol does not change the behavior once an 'error'
event is emitted. Therefore, the process will still crash if no
+regular 'error'
listener is installed.
Optional
[captureRest
...args: AnyRestAlias for emitter.on(eventName, listener)
.
Rest
...args: any[]queue.workingOn
with the worker names as keys.delByFunction
+queue to look in
+function name to delete any jobs with
+optional place to start looking in list (default: beginning of list)
+optional place to end looking in list (default: end of list)
+number of jobs deleted from queue
+Synchronously calls each of the listeners registered for the event named eventName
, in the order they were registered, passing the supplied arguments
+to each.
Returns true
if the event had listeners, false
otherwise.
import { EventEmitter } from 'node:events';
const myEmitter = new EventEmitter();
// First listener
myEmitter.on('event', function firstListener() {
console.log('Helloooo! first listener');
});
// Second listener
myEmitter.on('event', function secondListener(arg1, arg2) {
console.log(`event with parameters ${arg1}, ${arg2} in second listener`);
});
// Third listener
myEmitter.on('event', function thirdListener(...args) {
const parameters = args.join(', ');
console.log(`event with parameters ${parameters} in third listener`);
});
console.log(myEmitter.listeners('event'));
myEmitter.emit('event', 1, 2, 3, 4, 5);
// Prints:
// [
// [Function: firstListener],
// [Function: secondListener],
// [Function: thirdListener]
// ]
// Helloooo! first listener
// event with parameters 1, 2 in second listener
// event with parameters 1, 2, 3, 4, 5 in third listener
+
+
+Rest
...args: AnyRestjobs
to be worked by a worker)queueName
queue, and that queue will be worked down by available workers assigned to that queuequeueName
, it is likely that this job will not be excecuted at exactly the time specified, but shortly thereafter.queue.enqueue
queueName
, it is likely that this job will not be excecuted at exactly the delay specified, but shortly thereafter.queue.enqueue
Returns an array listing the events for which the emitter has registered
+listeners. The values in the array are strings or Symbol
s.
import { EventEmitter } from 'node:events';
const myEE = new EventEmitter();
myEE.on('foo', () => {});
myEE.on('bar', () => {});
const sym = Symbol('symbol');
myEE.on(sym, () => {});
console.log(myEE.eventNames());
// Prints: [ 'foo', 'bar', Symbol(symbol) ]
+
+
+failedJobs
is an array listing the data of the failed jobs. Each element looks like:{"worker": "host:pid", "queue": "test_queue", "payload": {"class":"slowJob", "queue":"test_queue", "args":[null]}, "exception": "TypeError", "error": "MyImport is not a function", "backtrace": [' at Worker.perform (/path/to/worker:111:24)', ' at <anonymous>'], "failed_at": "Fri Dec 12 2014 14:01:16 GMT-0800 (PST)"}\
+
+
+await queue.failed(0, -1)
Returns the current max listener value for the EventEmitter
which is either
+set by emitter.setMaxListeners(n)
or defaults to defaultMaxListeners.
Returns the number of listeners listening for the event named eventName
.
+If listener
is provided, it will return how many times the listener is found
+in the list of the listeners of the event.
The name of the event being listened for
+Optional
listener: FunctionThe event handler function
+Returns a copy of the array of listeners for the event named eventName
.
server.on('connection', (stream) => {
console.log('someone connected!');
});
console.log(util.inspect(server.listeners('connection')));
// Prints: [ [Function] ]
+
+
+Alias for emitter.removeListener()
.
Rest
...args: any[]Adds the listener
function to the beginning of the listeners array for the
+event named eventName
. No checks are made to see if the listener
has
+already been added. Multiple calls passing the same combination of eventName
+and listener
will result in the listener
being added, and called, multiple times.
server.prependListener('connection', (stream) => {
console.log('someone connected!');
});
+
+
+Returns a reference to the EventEmitter
, so that calls can be chained.
The name of the event.
+The callback function
+Rest
...args: any[]Adds a one-timelistener
function for the event named eventName
to the beginning of the listeners array. The next time eventName
is triggered, this
+listener is removed, and then invoked.
server.prependOnceListener('connection', (stream) => {
console.log('Ah, we have our first user!');
});
+
+
+Returns a reference to the EventEmitter
, so that calls can be chained.
The name of the event.
+The callback function
+Rest
...args: any[]Returns a copy of the array of listeners for the event named eventName
,
+including any wrappers (such as those created by .once()
).
import { EventEmitter } from 'node:events';
const emitter = new EventEmitter();
emitter.once('log', () => console.log('log once'));
// Returns a new Array with a function `onceWrapper` which has a property
// `listener` which contains the original listener bound above
const listeners = emitter.rawListeners('log');
const logFnWrapper = listeners[0];
// Logs "log once" to the console and does not unbind the `once` event
logFnWrapper.listener();
// Logs "log once" to the console and removes the listener
logFnWrapper();
emitter.on('log', () => console.log('log persistently'));
// Will return a new Array with a single function bound by `.on()` above
const newListeners = emitter.rawListeners('log');
// Logs "log persistently" twice
newListeners[0]();
emitter.emit('log');
+
+
+Removes all listeners, or those of the specified eventName
.
It is bad practice to remove listeners added elsewhere in the code,
+particularly when the EventEmitter
instance was created by some other
+component or module (e.g. sockets or file streams).
Returns a reference to the EventEmitter
, so that calls can be chained.
Optional
eventName: string | symbolRemoves the specified listener
from the listener array for the event named eventName
.
const callback = (stream) => {
console.log('someone connected!');
};
server.on('connection', callback);
// ...
server.removeListener('connection', callback);
+
+
+removeListener()
will remove, at most, one instance of a listener from the
+listener array. If any single listener has been added multiple times to the
+listener array for the specified eventName
, then removeListener()
must be
+called multiple times to remove each instance.
Once an event is emitted, all listeners attached to it at the
+time of emitting are called in order. This implies that any removeListener()
or removeAllListeners()
calls after emitting and before the last listener finishes execution
+will not remove them fromemit()
in progress. Subsequent events behave as expected.
import { EventEmitter } from 'node:events';
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter();
const callbackA = () => {
console.log('A');
myEmitter.removeListener('event', callbackB);
};
const callbackB = () => {
console.log('B');
};
myEmitter.on('event', callbackA);
myEmitter.on('event', callbackB);
// callbackA removes listener callbackB but it will still be called.
// Internal listener array at time of emit [callbackA, callbackB]
myEmitter.emit('event');
// Prints:
// A
// B
// callbackB is now removed.
// Internal listener array [callbackA]
myEmitter.emit('event');
// Prints:
// A
+
+
+Because listeners are managed using an internal array, calling this will
+change the position indices of any listener registered after the listener
+being removed. This will not impact the order in which listeners are called,
+but it means that any copies of the listener array as returned by
+the emitter.listeners()
method will need to be recreated.
When a single function has been added as a handler multiple times for a single
+event (as in the example below), removeListener()
will remove the most
+recently added instance. In the example the once('ping')
listener is removed:
import { EventEmitter } from 'node:events';
const ee = new EventEmitter();
function pong() {
console.log('pong');
}
ee.on('ping', pong);
ee.once('ping', pong);
ee.removeListener('ping', pong);
ee.emit('ping');
ee.emit('ping');
+
+
+Returns a reference to the EventEmitter
, so that calls can be chained.
Rest
...args: any[]By default EventEmitter
s will print a warning if more than 10
listeners are
+added for a particular event. This is a useful default that helps finding
+memory leaks. The emitter.setMaxListeners()
method allows the limit to be
+modified for this specific EventEmitter
instance. The value can be set to Infinity
(or 0
) to indicate an unlimited number of listeners.
Returns a reference to the EventEmitter
, so that calls can be chained.
Static
addExperimental
Listens once to the abort
event on the provided signal
.
Listening to the abort
event on abort signals is unsafe and may
+lead to resource leaks since another third party with the signal can
+call e.stopImmediatePropagation()
. Unfortunately Node.js cannot change
+this since it would violate the web standard. Additionally, the original
+API makes it easy to forget to remove listeners.
This API allows safely using AbortSignal
s in Node.js APIs by solving these
+two issues by listening to the event such that stopImmediatePropagation
does
+not prevent the listener from running.
Returns a disposable so that it may be unsubscribed from more easily.
+import { addAbortListener } from 'node:events';
function example(signal) {
let disposable;
try {
signal.addEventListener('abort', (e) => e.stopImmediatePropagation());
disposable = addAbortListener(signal, (e) => {
// Do something when signal is aborted.
});
} finally {
disposable?.[Symbol.dispose]();
}
}
+
+
+Disposable that removes the abort
listener.
Static
getReturns a copy of the array of listeners for the event named eventName
.
For EventEmitter
s this behaves exactly the same as calling .listeners
on
+the emitter.
For EventTarget
s this is the only way to get the event listeners for the
+event target. This is useful for debugging and diagnostic purposes.
import { getEventListeners, EventEmitter } from 'node:events';
{
const ee = new EventEmitter();
const listener = () => console.log('Events are fun');
ee.on('foo', listener);
console.log(getEventListeners(ee, 'foo')); // [ [Function: listener] ]
}
{
const et = new EventTarget();
const listener = () => console.log('Events are fun');
et.addEventListener('foo', listener);
console.log(getEventListeners(et, 'foo')); // [ [Function: listener] ]
}
+
+
+Static
getReturns the currently set max amount of listeners.
+For EventEmitter
s this behaves exactly the same as calling .getMaxListeners
on
+the emitter.
For EventTarget
s this is the only way to get the max event listeners for the
+event target. If the number of event handlers on a single EventTarget exceeds
+the max set, the EventTarget will print a warning.
import { getMaxListeners, setMaxListeners, EventEmitter } from 'node:events';
{
const ee = new EventEmitter();
console.log(getMaxListeners(ee)); // 10
setMaxListeners(11, ee);
console.log(getMaxListeners(ee)); // 11
}
{
const et = new EventTarget();
console.log(getMaxListeners(et)); // 10
setMaxListeners(11, et);
console.log(getMaxListeners(et)); // 11
}
+
+
+Static
listenerA class method that returns the number of listeners for the given eventName
registered on the given emitter
.
import { EventEmitter, listenerCount } from 'node:events';
const myEmitter = new EventEmitter();
myEmitter.on('event', () => {});
myEmitter.on('event', () => {});
console.log(listenerCount(myEmitter, 'event'));
// Prints: 2
+
+
+The emitter to query
+The event name
+Static
onimport { on, EventEmitter } from 'node:events';
import process from 'node:process';
const ee = new EventEmitter();
// Emit later on
process.nextTick(() => {
ee.emit('foo', 'bar');
ee.emit('foo', 42);
});
for await (const event of on(ee, 'foo')) {
// The execution of this inner block is synchronous and it
// processes one event at a time (even with await). Do not use
// if concurrent execution is required.
console.log(event); // prints ['bar'] [42]
}
// Unreachable here
+
+
+Returns an AsyncIterator
that iterates eventName
events. It will throw
+if the EventEmitter
emits 'error'
. It removes all listeners when
+exiting the loop. The value
returned by each iteration is an array
+composed of the emitted event arguments.
An AbortSignal
can be used to cancel waiting on events:
import { on, EventEmitter } from 'node:events';
import process from 'node:process';
const ac = new AbortController();
(async () => {
const ee = new EventEmitter();
// Emit later on
process.nextTick(() => {
ee.emit('foo', 'bar');
ee.emit('foo', 42);
});
for await (const event of on(ee, 'foo', { signal: ac.signal })) {
// The execution of this inner block is synchronous and it
// processes one event at a time (even with await). Do not use
// if concurrent execution is required.
console.log(event); // prints ['bar'] [42]
}
// Unreachable here
})();
process.nextTick(() => ac.abort());
+
+
+Use the close
option to specify an array of event names that will end the iteration:
import { on, EventEmitter } from 'node:events';
import process from 'node:process';
const ee = new EventEmitter();
// Emit later on
process.nextTick(() => {
ee.emit('foo', 'bar');
ee.emit('foo', 42);
ee.emit('close');
});
for await (const event of on(ee, 'foo', { close: ['close'] })) {
console.log(event); // prints ['bar'] [42]
}
// the loop will exit after 'close' is emitted
console.log('done'); // prints 'done'
+
+
+Optional
options: StaticEventEmitterIteratorOptionsAn AsyncIterator
that iterates eventName
events emitted by the emitter
Optional
options: StaticEventEmitterIteratorOptionsStatic
onceCreates a Promise
that is fulfilled when the EventEmitter
emits the given
+event or that is rejected if the EventEmitter
emits 'error'
while waiting.
+The Promise
will resolve with an array of all the arguments emitted to the
+given event.
This method is intentionally generic and works with the web platform EventTarget interface, which has no special'error'
event
+semantics and does not listen to the 'error'
event.
import { once, EventEmitter } from 'node:events';
import process from 'node:process';
const ee = new EventEmitter();
process.nextTick(() => {
ee.emit('myevent', 42);
});
const [value] = await once(ee, 'myevent');
console.log(value);
const err = new Error('kaboom');
process.nextTick(() => {
ee.emit('error', err);
});
try {
await once(ee, 'myevent');
} catch (err) {
console.error('error happened', err);
}
+
+
+The special handling of the 'error'
event is only used when events.once()
is used to wait for another event. If events.once()
is used to wait for the
+'error'
event itself, then it is treated as any other kind of event without
+special handling:
import { EventEmitter, once } from 'node:events';
const ee = new EventEmitter();
once(ee, 'error')
.then(([err]) => console.log('ok', err.message))
.catch((err) => console.error('error', err.message));
ee.emit('error', new Error('boom'));
// Prints: ok boom
+
+
+An AbortSignal
can be used to cancel waiting for the event:
import { EventEmitter, once } from 'node:events';
const ee = new EventEmitter();
const ac = new AbortController();
async function foo(emitter, event, signal) {
try {
await once(emitter, event, { signal });
console.log('event emitted!');
} catch (error) {
if (error.name === 'AbortError') {
console.error('Waiting for the event was canceled!');
} else {
console.error('There was an error', error.message);
}
}
}
foo(ee, 'foo', ac.signal);
ac.abort(); // Abort waiting for the event
ee.emit('foo'); // Prints: Waiting for the event was canceled!
+
+
+Optional
options: StaticEventEmitterOptionsOptional
options: StaticEventEmitterOptionsStatic
setimport { setMaxListeners, EventEmitter } from 'node:events';
const target = new EventTarget();
const emitter = new EventEmitter();
setMaxListeners(5, target, emitter);
+
+
+Optional
n: numberA non-negative number. The maximum number of listeners per EventTarget
event.
Rest
...eventTargets: (EventTarget | EventEmitter<DefaultEventMap>)[]Static
Readonly
captureValue: Symbol.for('nodejs.rejection')
See how to write a custom rejection handler
.
Static
captureValue: boolean
+Change the default captureRejections
option on all new EventEmitter
objects.
Static
defaultBy 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 allEventEmitter
instances, the events.defaultMaxListeners
property
+can be used. If this value is not a positive number, a RangeError
is thrown.
Take caution when setting the events.defaultMaxListeners
because the
+change affects all EventEmitter
instances, including those created before
+the change is made. However, calling emitter.setMaxListeners(n)
still has
+precedence over events.defaultMaxListeners
.
This is not a hard limit. The EventEmitter
instance will allow
+more listeners to be added but will output a trace warning to stderr indicating
+that a "possible EventEmitter memory leak" has been detected. For any single
+EventEmitter
, the emitter.getMaxListeners()
and emitter.setMaxListeners()
methods can be used to
+temporarily avoid this warning:
import { EventEmitter } from 'node:events';
const emitter = new EventEmitter();
emitter.setMaxListeners(emitter.getMaxListeners() + 1);
emitter.once('event', () => {
// do stuff
emitter.setMaxListeners(Math.max(emitter.getMaxListeners() - 1, 0));
});
+
+
+The --trace-warnings
command-line flag can be used to display the
+stack trace for such warnings.
The emitted warning can be inspected with process.on('warning')
and will
+have the additional emitter
, type
, and count
properties, referring to
+the event emitter instance, the event's name and the number of attached
+listeners, respectively.
+Its name
property is set to 'MaxListenersExceededWarning'
.
Static
Readonly
errorThis 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.
Installing a listener using this symbol does not change the behavior once an 'error'
event is emitted. Therefore, the process will still crash if no
+regular 'error'
listener is installed.
Optional
[captureRest
...args: AnyRestAlias for emitter.on(eventName, listener)
.
Rest
...args: any[]Synchronously calls each of the listeners registered for the event named eventName
, in the order they were registered, passing the supplied arguments
+to each.
Returns true
if the event had listeners, false
otherwise.
import { EventEmitter } from 'node:events';
const myEmitter = new EventEmitter();
// First listener
myEmitter.on('event', function firstListener() {
console.log('Helloooo! first listener');
});
// Second listener
myEmitter.on('event', function secondListener(arg1, arg2) {
console.log(`event with parameters ${arg1}, ${arg2} in second listener`);
});
// Third listener
myEmitter.on('event', function thirdListener(...args) {
const parameters = args.join(', ');
console.log(`event with parameters ${parameters} in third listener`);
});
console.log(myEmitter.listeners('event'));
myEmitter.emit('event', 1, 2, 3, 4, 5);
// Prints:
// [
// [Function: firstListener],
// [Function: secondListener],
// [Function: thirdListener]
// ]
// Helloooo! first listener
// event with parameters 1, 2 in second listener
// event with parameters 1, 2, 3, 4, 5 in third listener
+
+
+Rest
...args: AnyRestReturns an array listing the events for which the emitter has registered
+listeners. The values in the array are strings or Symbol
s.
import { EventEmitter } from 'node:events';
const myEE = new EventEmitter();
myEE.on('foo', () => {});
myEE.on('bar', () => {});
const sym = Symbol('symbol');
myEE.on(sym, () => {});
console.log(myEE.eventNames());
// Prints: [ 'foo', 'bar', Symbol(symbol) ]
+
+
+Returns the current max listener value for the EventEmitter
which is either
+set by emitter.setMaxListeners(n)
or defaults to defaultMaxListeners.
Returns the number of listeners listening for the event named eventName
.
+If listener
is provided, it will return how many times the listener is found
+in the list of the listeners of the event.
The name of the event being listened for
+Optional
listener: FunctionThe event handler function
+Returns a copy of the array of listeners for the event named eventName
.
server.on('connection', (stream) => {
console.log('someone connected!');
});
console.log(util.inspect(server.listeners('connection')));
// Prints: [ [Function] ]
+
+
+Alias for emitter.removeListener()
.
Rest
...args: any[]Adds the listener
function to the beginning of the listeners array for the
+event named eventName
. No checks are made to see if the listener
has
+already been added. Multiple calls passing the same combination of eventName
+and listener
will result in the listener
being added, and called, multiple times.
server.prependListener('connection', (stream) => {
console.log('someone connected!');
});
+
+
+Returns a reference to the EventEmitter
, so that calls can be chained.
The name of the event.
+The callback function
+Rest
...args: any[]Adds a one-timelistener
function for the event named eventName
to the beginning of the listeners array. The next time eventName
is triggered, this
+listener is removed, and then invoked.
server.prependOnceListener('connection', (stream) => {
console.log('Ah, we have our first user!');
});
+
+
+Returns a reference to the EventEmitter
, so that calls can be chained.
The name of the event.
+The callback function
+Rest
...args: any[]Returns a copy of the array of listeners for the event named eventName
,
+including any wrappers (such as those created by .once()
).
import { EventEmitter } from 'node:events';
const emitter = new EventEmitter();
emitter.once('log', () => console.log('log once'));
// Returns a new Array with a function `onceWrapper` which has a property
// `listener` which contains the original listener bound above
const listeners = emitter.rawListeners('log');
const logFnWrapper = listeners[0];
// Logs "log once" to the console and does not unbind the `once` event
logFnWrapper.listener();
// Logs "log once" to the console and removes the listener
logFnWrapper();
emitter.on('log', () => console.log('log persistently'));
// Will return a new Array with a single function bound by `.on()` above
const newListeners = emitter.rawListeners('log');
// Logs "log persistently" twice
newListeners[0]();
emitter.emit('log');
+
+
+Removes the specified listener
from the listener array for the event named eventName
.
const callback = (stream) => {
console.log('someone connected!');
};
server.on('connection', callback);
// ...
server.removeListener('connection', callback);
+
+
+removeListener()
will remove, at most, one instance of a listener from the
+listener array. If any single listener has been added multiple times to the
+listener array for the specified eventName
, then removeListener()
must be
+called multiple times to remove each instance.
Once an event is emitted, all listeners attached to it at the
+time of emitting are called in order. This implies that any removeListener()
or removeAllListeners()
calls after emitting and before the last listener finishes execution
+will not remove them fromemit()
in progress. Subsequent events behave as expected.
import { EventEmitter } from 'node:events';
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter();
const callbackA = () => {
console.log('A');
myEmitter.removeListener('event', callbackB);
};
const callbackB = () => {
console.log('B');
};
myEmitter.on('event', callbackA);
myEmitter.on('event', callbackB);
// callbackA removes listener callbackB but it will still be called.
// Internal listener array at time of emit [callbackA, callbackB]
myEmitter.emit('event');
// Prints:
// A
// B
// callbackB is now removed.
// Internal listener array [callbackA]
myEmitter.emit('event');
// Prints:
// A
+
+
+Because listeners are managed using an internal array, calling this will
+change the position indices of any listener registered after the listener
+being removed. This will not impact the order in which listeners are called,
+but it means that any copies of the listener array as returned by
+the emitter.listeners()
method will need to be recreated.
When a single function has been added as a handler multiple times for a single
+event (as in the example below), removeListener()
will remove the most
+recently added instance. In the example the once('ping')
listener is removed:
import { EventEmitter } from 'node:events';
const ee = new EventEmitter();
function pong() {
console.log('pong');
}
ee.on('ping', pong);
ee.once('ping', pong);
ee.removeListener('ping', pong);
ee.emit('ping');
ee.emit('ping');
+
+
+Returns a reference to the EventEmitter
, so that calls can be chained.
Rest
...args: any[]By default EventEmitter
s will print a warning if more than 10
listeners are
+added for a particular event. This is a useful default that helps finding
+memory leaks. The emitter.setMaxListeners()
method allows the limit to be
+modified for this specific EventEmitter
instance. The value can be set to Infinity
(or 0
) to indicate an unlimited number of listeners.
Returns a reference to the EventEmitter
, so that calls can be chained.
Static
addExperimental
Listens once to the abort
event on the provided signal
.
Listening to the abort
event on abort signals is unsafe and may
+lead to resource leaks since another third party with the signal can
+call e.stopImmediatePropagation()
. Unfortunately Node.js cannot change
+this since it would violate the web standard. Additionally, the original
+API makes it easy to forget to remove listeners.
This API allows safely using AbortSignal
s in Node.js APIs by solving these
+two issues by listening to the event such that stopImmediatePropagation
does
+not prevent the listener from running.
Returns a disposable so that it may be unsubscribed from more easily.
+import { addAbortListener } from 'node:events';
function example(signal) {
let disposable;
try {
signal.addEventListener('abort', (e) => e.stopImmediatePropagation());
disposable = addAbortListener(signal, (e) => {
// Do something when signal is aborted.
});
} finally {
disposable?.[Symbol.dispose]();
}
}
+
+
+Disposable that removes the abort
listener.
Static
getReturns a copy of the array of listeners for the event named eventName
.
For EventEmitter
s this behaves exactly the same as calling .listeners
on
+the emitter.
For EventTarget
s this is the only way to get the event listeners for the
+event target. This is useful for debugging and diagnostic purposes.
import { getEventListeners, EventEmitter } from 'node:events';
{
const ee = new EventEmitter();
const listener = () => console.log('Events are fun');
ee.on('foo', listener);
console.log(getEventListeners(ee, 'foo')); // [ [Function: listener] ]
}
{
const et = new EventTarget();
const listener = () => console.log('Events are fun');
et.addEventListener('foo', listener);
console.log(getEventListeners(et, 'foo')); // [ [Function: listener] ]
}
+
+
+Static
getReturns the currently set max amount of listeners.
+For EventEmitter
s this behaves exactly the same as calling .getMaxListeners
on
+the emitter.
For EventTarget
s this is the only way to get the max event listeners for the
+event target. If the number of event handlers on a single EventTarget exceeds
+the max set, the EventTarget will print a warning.
import { getMaxListeners, setMaxListeners, EventEmitter } from 'node:events';
{
const ee = new EventEmitter();
console.log(getMaxListeners(ee)); // 10
setMaxListeners(11, ee);
console.log(getMaxListeners(ee)); // 11
}
{
const et = new EventTarget();
console.log(getMaxListeners(et)); // 10
setMaxListeners(11, et);
console.log(getMaxListeners(et)); // 11
}
+
+
+Static
listenerA class method that returns the number of listeners for the given eventName
registered on the given emitter
.
import { EventEmitter, listenerCount } from 'node:events';
const myEmitter = new EventEmitter();
myEmitter.on('event', () => {});
myEmitter.on('event', () => {});
console.log(listenerCount(myEmitter, 'event'));
// Prints: 2
+
+
+The emitter to query
+The event name
+Static
onimport { on, EventEmitter } from 'node:events';
import process from 'node:process';
const ee = new EventEmitter();
// Emit later on
process.nextTick(() => {
ee.emit('foo', 'bar');
ee.emit('foo', 42);
});
for await (const event of on(ee, 'foo')) {
// The execution of this inner block is synchronous and it
// processes one event at a time (even with await). Do not use
// if concurrent execution is required.
console.log(event); // prints ['bar'] [42]
}
// Unreachable here
+
+
+Returns an AsyncIterator
that iterates eventName
events. It will throw
+if the EventEmitter
emits 'error'
. It removes all listeners when
+exiting the loop. The value
returned by each iteration is an array
+composed of the emitted event arguments.
An AbortSignal
can be used to cancel waiting on events:
import { on, EventEmitter } from 'node:events';
import process from 'node:process';
const ac = new AbortController();
(async () => {
const ee = new EventEmitter();
// Emit later on
process.nextTick(() => {
ee.emit('foo', 'bar');
ee.emit('foo', 42);
});
for await (const event of on(ee, 'foo', { signal: ac.signal })) {
// The execution of this inner block is synchronous and it
// processes one event at a time (even with await). Do not use
// if concurrent execution is required.
console.log(event); // prints ['bar'] [42]
}
// Unreachable here
})();
process.nextTick(() => ac.abort());
+
+
+Use the close
option to specify an array of event names that will end the iteration:
import { on, EventEmitter } from 'node:events';
import process from 'node:process';
const ee = new EventEmitter();
// Emit later on
process.nextTick(() => {
ee.emit('foo', 'bar');
ee.emit('foo', 42);
ee.emit('close');
});
for await (const event of on(ee, 'foo', { close: ['close'] })) {
console.log(event); // prints ['bar'] [42]
}
// the loop will exit after 'close' is emitted
console.log('done'); // prints 'done'
+
+
+Optional
options: StaticEventEmitterIteratorOptionsAn AsyncIterator
that iterates eventName
events emitted by the emitter
Optional
options: StaticEventEmitterIteratorOptionsStatic
onceCreates a Promise
that is fulfilled when the EventEmitter
emits the given
+event or that is rejected if the EventEmitter
emits 'error'
while waiting.
+The Promise
will resolve with an array of all the arguments emitted to the
+given event.
This method is intentionally generic and works with the web platform EventTarget interface, which has no special'error'
event
+semantics and does not listen to the 'error'
event.
import { once, EventEmitter } from 'node:events';
import process from 'node:process';
const ee = new EventEmitter();
process.nextTick(() => {
ee.emit('myevent', 42);
});
const [value] = await once(ee, 'myevent');
console.log(value);
const err = new Error('kaboom');
process.nextTick(() => {
ee.emit('error', err);
});
try {
await once(ee, 'myevent');
} catch (err) {
console.error('error happened', err);
}
+
+
+The special handling of the 'error'
event is only used when events.once()
is used to wait for another event. If events.once()
is used to wait for the
+'error'
event itself, then it is treated as any other kind of event without
+special handling:
import { EventEmitter, once } from 'node:events';
const ee = new EventEmitter();
once(ee, 'error')
.then(([err]) => console.log('ok', err.message))
.catch((err) => console.error('error', err.message));
ee.emit('error', new Error('boom'));
// Prints: ok boom
+
+
+An AbortSignal
can be used to cancel waiting for the event:
import { EventEmitter, once } from 'node:events';
const ee = new EventEmitter();
const ac = new AbortController();
async function foo(emitter, event, signal) {
try {
await once(emitter, event, { signal });
console.log('event emitted!');
} catch (error) {
if (error.name === 'AbortError') {
console.error('Waiting for the event was canceled!');
} else {
console.error('There was an error', error.message);
}
}
}
foo(ee, 'foo', ac.signal);
ac.abort(); // Abort waiting for the event
ee.emit('foo'); // Prints: Waiting for the event was canceled!
+
+
+Optional
options: StaticEventEmitterOptionsOptional
options: StaticEventEmitterOptionsStatic
setimport { setMaxListeners, EventEmitter } from 'node:events';
const target = new EventTarget();
const emitter = new EventEmitter();
setMaxListeners(5, target, emitter);
+
+
+Optional
n: numberA non-negative number. The maximum number of listeners per EventTarget
event.
Rest
...eventTargets: (EventTarget | EventEmitter<DefaultEventMap>)[]Static
Readonly
captureValue: Symbol.for('nodejs.rejection')
See how to write a custom rejection handler
.
Static
captureValue: boolean
+Change the default captureRejections
option on all new EventEmitter
objects.
Static
defaultBy 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 allEventEmitter
instances, the events.defaultMaxListeners
property
+can be used. If this value is not a positive number, a RangeError
is thrown.
Take caution when setting the events.defaultMaxListeners
because the
+change affects all EventEmitter
instances, including those created before
+the change is made. However, calling emitter.setMaxListeners(n)
still has
+precedence over events.defaultMaxListeners
.
This is not a hard limit. The EventEmitter
instance will allow
+more listeners to be added but will output a trace warning to stderr indicating
+that a "possible EventEmitter memory leak" has been detected. For any single
+EventEmitter
, the emitter.getMaxListeners()
and emitter.setMaxListeners()
methods can be used to
+temporarily avoid this warning:
import { EventEmitter } from 'node:events';
const emitter = new EventEmitter();
emitter.setMaxListeners(emitter.getMaxListeners() + 1);
emitter.once('event', () => {
// do stuff
emitter.setMaxListeners(Math.max(emitter.getMaxListeners() - 1, 0));
});
+
+
+The --trace-warnings
command-line flag can be used to display the
+stack trace for such warnings.
The emitted warning can be inspected with process.on('warning')
and will
+have the additional emitter
, type
, and count
properties, referring to
+the event emitter instance, the event's name and the number of attached
+listeners, respectively.
+Its name
property is set to 'MaxListenersExceededWarning'
.
Static
Readonly
errorThis 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.
Installing a listener using this symbol does not change the behavior once an 'error'
event is emitted. Therefore, the process will still crash if no
+regular 'error'
listener is installed.
Optional
[captureRest
...args: AnyRestAlias for emitter.on(eventName, listener)
.
Rest
...args: any[]Synchronously calls each of the listeners registered for the event named eventName
, in the order they were registered, passing the supplied arguments
+to each.
Returns true
if the event had listeners, false
otherwise.
import { EventEmitter } from 'node:events';
const myEmitter = new EventEmitter();
// First listener
myEmitter.on('event', function firstListener() {
console.log('Helloooo! first listener');
});
// Second listener
myEmitter.on('event', function secondListener(arg1, arg2) {
console.log(`event with parameters ${arg1}, ${arg2} in second listener`);
});
// Third listener
myEmitter.on('event', function thirdListener(...args) {
const parameters = args.join(', ');
console.log(`event with parameters ${parameters} in third listener`);
});
console.log(myEmitter.listeners('event'));
myEmitter.emit('event', 1, 2, 3, 4, 5);
// Prints:
// [
// [Function: firstListener],
// [Function: secondListener],
// [Function: thirdListener]
// ]
// Helloooo! first listener
// event with parameters 1, 2 in second listener
// event with parameters 1, 2, 3, 4, 5 in third listener
+
+
+Rest
...args: AnyRestReturns an array listing the events for which the emitter has registered
+listeners. The values in the array are strings or Symbol
s.
import { EventEmitter } from 'node:events';
const myEE = new EventEmitter();
myEE.on('foo', () => {});
myEE.on('bar', () => {});
const sym = Symbol('symbol');
myEE.on(sym, () => {});
console.log(myEE.eventNames());
// Prints: [ 'foo', 'bar', Symbol(symbol) ]
+
+
+Returns the current max listener value for the EventEmitter
which is either
+set by emitter.setMaxListeners(n)
or defaults to defaultMaxListeners.
Returns the number of listeners listening for the event named eventName
.
+If listener
is provided, it will return how many times the listener is found
+in the list of the listeners of the event.
The name of the event being listened for
+Optional
listener: FunctionThe event handler function
+Returns a copy of the array of listeners for the event named eventName
.
server.on('connection', (stream) => {
console.log('someone connected!');
});
console.log(util.inspect(server.listeners('connection')));
// Prints: [ [Function] ]
+
+
+Alias for emitter.removeListener()
.
Rest
...args: any[]Adds the listener
function to the beginning of the listeners array for the
+event named eventName
. No checks are made to see if the listener
has
+already been added. Multiple calls passing the same combination of eventName
+and listener
will result in the listener
being added, and called, multiple times.
server.prependListener('connection', (stream) => {
console.log('someone connected!');
});
+
+
+Returns a reference to the EventEmitter
, so that calls can be chained.
The name of the event.
+The callback function
+Rest
...args: any[]Adds a one-timelistener
function for the event named eventName
to the beginning of the listeners array. The next time eventName
is triggered, this
+listener is removed, and then invoked.
server.prependOnceListener('connection', (stream) => {
console.log('Ah, we have our first user!');
});
+
+
+Returns a reference to the EventEmitter
, so that calls can be chained.
The name of the event.
+The callback function
+Rest
...args: any[]Returns a copy of the array of listeners for the event named eventName
,
+including any wrappers (such as those created by .once()
).
import { EventEmitter } from 'node:events';
const emitter = new EventEmitter();
emitter.once('log', () => console.log('log once'));
// Returns a new Array with a function `onceWrapper` which has a property
// `listener` which contains the original listener bound above
const listeners = emitter.rawListeners('log');
const logFnWrapper = listeners[0];
// Logs "log once" to the console and does not unbind the `once` event
logFnWrapper.listener();
// Logs "log once" to the console and removes the listener
logFnWrapper();
emitter.on('log', () => console.log('log persistently'));
// Will return a new Array with a single function bound by `.on()` above
const newListeners = emitter.rawListeners('log');
// Logs "log persistently" twice
newListeners[0]();
emitter.emit('log');
+
+
+Removes the specified listener
from the listener array for the event named eventName
.
const callback = (stream) => {
console.log('someone connected!');
};
server.on('connection', callback);
// ...
server.removeListener('connection', callback);
+
+
+removeListener()
will remove, at most, one instance of a listener from the
+listener array. If any single listener has been added multiple times to the
+listener array for the specified eventName
, then removeListener()
must be
+called multiple times to remove each instance.
Once an event is emitted, all listeners attached to it at the
+time of emitting are called in order. This implies that any removeListener()
or removeAllListeners()
calls after emitting and before the last listener finishes execution
+will not remove them fromemit()
in progress. Subsequent events behave as expected.
import { EventEmitter } from 'node:events';
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter();
const callbackA = () => {
console.log('A');
myEmitter.removeListener('event', callbackB);
};
const callbackB = () => {
console.log('B');
};
myEmitter.on('event', callbackA);
myEmitter.on('event', callbackB);
// callbackA removes listener callbackB but it will still be called.
// Internal listener array at time of emit [callbackA, callbackB]
myEmitter.emit('event');
// Prints:
// A
// B
// callbackB is now removed.
// Internal listener array [callbackA]
myEmitter.emit('event');
// Prints:
// A
+
+
+Because listeners are managed using an internal array, calling this will
+change the position indices of any listener registered after the listener
+being removed. This will not impact the order in which listeners are called,
+but it means that any copies of the listener array as returned by
+the emitter.listeners()
method will need to be recreated.
When a single function has been added as a handler multiple times for a single
+event (as in the example below), removeListener()
will remove the most
+recently added instance. In the example the once('ping')
listener is removed:
import { EventEmitter } from 'node:events';
const ee = new EventEmitter();
function pong() {
console.log('pong');
}
ee.on('ping', pong);
ee.once('ping', pong);
ee.removeListener('ping', pong);
ee.emit('ping');
ee.emit('ping');
+
+
+Returns a reference to the EventEmitter
, so that calls can be chained.
Rest
...args: any[]By default EventEmitter
s will print a warning if more than 10
listeners are
+added for a particular event. This is a useful default that helps finding
+memory leaks. The emitter.setMaxListeners()
method allows the limit to be
+modified for this specific EventEmitter
instance. The value can be set to Infinity
(or 0
) to indicate an unlimited number of listeners.
Returns a reference to the EventEmitter
, so that calls can be chained.
Static
addExperimental
Listens once to the abort
event on the provided signal
.
Listening to the abort
event on abort signals is unsafe and may
+lead to resource leaks since another third party with the signal can
+call e.stopImmediatePropagation()
. Unfortunately Node.js cannot change
+this since it would violate the web standard. Additionally, the original
+API makes it easy to forget to remove listeners.
This API allows safely using AbortSignal
s in Node.js APIs by solving these
+two issues by listening to the event such that stopImmediatePropagation
does
+not prevent the listener from running.
Returns a disposable so that it may be unsubscribed from more easily.
+import { addAbortListener } from 'node:events';
function example(signal) {
let disposable;
try {
signal.addEventListener('abort', (e) => e.stopImmediatePropagation());
disposable = addAbortListener(signal, (e) => {
// Do something when signal is aborted.
});
} finally {
disposable?.[Symbol.dispose]();
}
}
+
+
+Disposable that removes the abort
listener.
Static
getReturns a copy of the array of listeners for the event named eventName
.
For EventEmitter
s this behaves exactly the same as calling .listeners
on
+the emitter.
For EventTarget
s this is the only way to get the event listeners for the
+event target. This is useful for debugging and diagnostic purposes.
import { getEventListeners, EventEmitter } from 'node:events';
{
const ee = new EventEmitter();
const listener = () => console.log('Events are fun');
ee.on('foo', listener);
console.log(getEventListeners(ee, 'foo')); // [ [Function: listener] ]
}
{
const et = new EventTarget();
const listener = () => console.log('Events are fun');
et.addEventListener('foo', listener);
console.log(getEventListeners(et, 'foo')); // [ [Function: listener] ]
}
+
+
+Static
getReturns the currently set max amount of listeners.
+For EventEmitter
s this behaves exactly the same as calling .getMaxListeners
on
+the emitter.
For EventTarget
s this is the only way to get the max event listeners for the
+event target. If the number of event handlers on a single EventTarget exceeds
+the max set, the EventTarget will print a warning.
import { getMaxListeners, setMaxListeners, EventEmitter } from 'node:events';
{
const ee = new EventEmitter();
console.log(getMaxListeners(ee)); // 10
setMaxListeners(11, ee);
console.log(getMaxListeners(ee)); // 11
}
{
const et = new EventTarget();
console.log(getMaxListeners(et)); // 10
setMaxListeners(11, et);
console.log(getMaxListeners(et)); // 11
}
+
+
+Static
listenerA class method that returns the number of listeners for the given eventName
registered on the given emitter
.
import { EventEmitter, listenerCount } from 'node:events';
const myEmitter = new EventEmitter();
myEmitter.on('event', () => {});
myEmitter.on('event', () => {});
console.log(listenerCount(myEmitter, 'event'));
// Prints: 2
+
+
+The emitter to query
+The event name
+Static
onimport { on, EventEmitter } from 'node:events';
import process from 'node:process';
const ee = new EventEmitter();
// Emit later on
process.nextTick(() => {
ee.emit('foo', 'bar');
ee.emit('foo', 42);
});
for await (const event of on(ee, 'foo')) {
// The execution of this inner block is synchronous and it
// processes one event at a time (even with await). Do not use
// if concurrent execution is required.
console.log(event); // prints ['bar'] [42]
}
// Unreachable here
+
+
+Returns an AsyncIterator
that iterates eventName
events. It will throw
+if the EventEmitter
emits 'error'
. It removes all listeners when
+exiting the loop. The value
returned by each iteration is an array
+composed of the emitted event arguments.
An AbortSignal
can be used to cancel waiting on events:
import { on, EventEmitter } from 'node:events';
import process from 'node:process';
const ac = new AbortController();
(async () => {
const ee = new EventEmitter();
// Emit later on
process.nextTick(() => {
ee.emit('foo', 'bar');
ee.emit('foo', 42);
});
for await (const event of on(ee, 'foo', { signal: ac.signal })) {
// The execution of this inner block is synchronous and it
// processes one event at a time (even with await). Do not use
// if concurrent execution is required.
console.log(event); // prints ['bar'] [42]
}
// Unreachable here
})();
process.nextTick(() => ac.abort());
+
+
+Use the close
option to specify an array of event names that will end the iteration:
import { on, EventEmitter } from 'node:events';
import process from 'node:process';
const ee = new EventEmitter();
// Emit later on
process.nextTick(() => {
ee.emit('foo', 'bar');
ee.emit('foo', 42);
ee.emit('close');
});
for await (const event of on(ee, 'foo', { close: ['close'] })) {
console.log(event); // prints ['bar'] [42]
}
// the loop will exit after 'close' is emitted
console.log('done'); // prints 'done'
+
+
+Optional
options: StaticEventEmitterIteratorOptionsAn AsyncIterator
that iterates eventName
events emitted by the emitter
Optional
options: StaticEventEmitterIteratorOptionsStatic
onceCreates a Promise
that is fulfilled when the EventEmitter
emits the given
+event or that is rejected if the EventEmitter
emits 'error'
while waiting.
+The Promise
will resolve with an array of all the arguments emitted to the
+given event.
This method is intentionally generic and works with the web platform EventTarget interface, which has no special'error'
event
+semantics and does not listen to the 'error'
event.
import { once, EventEmitter } from 'node:events';
import process from 'node:process';
const ee = new EventEmitter();
process.nextTick(() => {
ee.emit('myevent', 42);
});
const [value] = await once(ee, 'myevent');
console.log(value);
const err = new Error('kaboom');
process.nextTick(() => {
ee.emit('error', err);
});
try {
await once(ee, 'myevent');
} catch (err) {
console.error('error happened', err);
}
+
+
+The special handling of the 'error'
event is only used when events.once()
is used to wait for another event. If events.once()
is used to wait for the
+'error'
event itself, then it is treated as any other kind of event without
+special handling:
import { EventEmitter, once } from 'node:events';
const ee = new EventEmitter();
once(ee, 'error')
.then(([err]) => console.log('ok', err.message))
.catch((err) => console.error('error', err.message));
ee.emit('error', new Error('boom'));
// Prints: ok boom
+
+
+An AbortSignal
can be used to cancel waiting for the event:
import { EventEmitter, once } from 'node:events';
const ee = new EventEmitter();
const ac = new AbortController();
async function foo(emitter, event, signal) {
try {
await once(emitter, event, { signal });
console.log('event emitted!');
} catch (error) {
if (error.name === 'AbortError') {
console.error('Waiting for the event was canceled!');
} else {
console.error('There was an error', error.message);
}
}
}
foo(ee, 'foo', ac.signal);
ac.abort(); // Abort waiting for the event
ee.emit('foo'); // Prints: Waiting for the event was canceled!
+
+
+Optional
options: StaticEventEmitterOptionsOptional
options: StaticEventEmitterOptionsStatic
setimport { setMaxListeners, EventEmitter } from 'node:events';
const target = new EventTarget();
const emitter = new EventEmitter();
setMaxListeners(5, target, emitter);
+
+
+Optional
n: numberA non-negative number. The maximum number of listeners per EventTarget
event.
Rest
...eventTargets: (EventTarget | EventEmitter<DefaultEventMap>)[]Distributed delayed jobs in nodejs. Resque is a background job system backed by Redis (version 2.6.0 and up required). It includes priority queues, plugins, locking, delayed jobs, and more! This project is a very opinionated but API-compatible with Resque and Sidekiq (caveats). We also implement some of the popular Resque plugins, including resque-scheduler and resque-retry
+The full API documentation for this package is automatically generated from the main
via typedoc branch and published to https://node-resque.actionherojs.com/
Resque is a queue based task processing system that can be thought of as a "Kanban" style factory. Workers in this factory can each only work one Job at a time. They pull Jobs from Queues and work them to completion (or failure). Each Job has two parts: instructions on how to complete the job (the perform
function), and any inputs necessary to complete the Job.
In our factory example, Queues are analogous to conveyor belts. Jobs are placed on the belts (Queues) and are held in order waiting for a Worker to pick them up. There are three types of Queues: regular work Queues, Delayed Job Queues, and the Failed Job Queue. The Delayed Job Queues contains Job definitions that are intended to be worked at or in a specified time. The Failed Job Queue is where Workers place any Jobs that have failed during execution.
+Our Workers are the heart of the factory. Each Worker is assigned one or more Queues to check for work. After taking a Job from a Queue the Worker attempts to complete the Job. If successful, they go back to check out more work from the Queues. However, if there is a failure, the Worker records the job and its inputs in the Failed Jobs Queue before going back for more work.
+The Scheduler can be thought of as a specialized type of Worker. Unlike other Workers, the Scheduler does not execute any Jobs, instead it manages the Delayed Job Queue. As Job definitions are added to the Delayed Job Queue they must specify when they can become available for execution. The Scheduler constantly checks to see if any Delayed Jobs are ready to execute. When a Delayed Job becomes ready for execution the Scheduler places a new instance of that Job in its defined Queue.
+You can read the API docs for Node Resque @ node-resque.actionherojs.com. These are generated automatically from the master branch via TypeDoc
+I learn best by examples:
+import { Worker, Plugins, Scheduler, Queue } from "node-resque";
async function boot() {
// ////////////////////////
// SET UP THE CONNECTION //
// ////////////////////////
const connectionDetails = {
pkg: "ioredis",
host: "127.0.0.1",
password: null,
port: 6379,
database: 0,
// namespace: 'resque',
// looping: true,
// options: {password: 'abc'},
};
// ///////////////////////////
// DEFINE YOUR WORKER TASKS //
// ///////////////////////////
let jobsToComplete = 0;
const jobs = {
add: {
plugins: [Plugins.JobLock],
pluginOptions: {
JobLock: { reEnqueue: true },
},
perform: async (a, b) => {
await new Promise((resolve) => {
setTimeout(resolve, 1000);
});
jobsToComplete--;
tryShutdown();
const answer = a + b;
return answer;
},
},
subtract: {
perform: (a, b) => {
jobsToComplete--;
tryShutdown();
const answer = a - b;
return answer;
},
},
};
// just a helper for this demo
async function tryShutdown() {
if (jobsToComplete === 0) {
await new Promise((resolve) => {
setTimeout(resolve, 500);
});
await scheduler.end();
await worker.end();
process.exit();
}
}
// /////////////////
// START A WORKER //
// /////////////////
const worker = new Worker(
{ connection: connectionDetails, queues: ["math", "otherQueue"] },
jobs,
);
await worker.connect();
worker.start();
// ////////////////////
// START A SCHEDULER //
// ////////////////////
const scheduler = new Scheduler({ connection: connectionDetails });
await scheduler.connect();
scheduler.start();
// //////////////////////
// REGISTER FOR EVENTS //
// //////////////////////
worker.on("start", () => {
console.log("worker started");
});
worker.on("end", () => {
console.log("worker ended");
});
worker.on("cleaning_worker", (worker, pid) => {
console.log(`cleaning old worker ${worker}`);
});
worker.on("poll", (queue) => {
console.log(`worker polling ${queue}`);
});
worker.on("ping", (time) => {
console.log(`worker check in @ ${time}`);
});
worker.on("job", (queue, job) => {
console.log(`working job ${queue} ${JSON.stringify(job)}`);
});
worker.on("reEnqueue", (queue, job, plugin) => {
console.log(`reEnqueue job (${plugin}) ${queue} ${JSON.stringify(job)}`);
});
worker.on("success", (queue, job, result, duration) => {
console.log(
`job success ${queue} ${JSON.stringify(
job,
)} >> ${result} (${duration}ms)`,
);
});
worker.on("failure", (queue, job, failure, duration) => {
console.log(
`job failure ${queue} ${JSON.stringify(
job,
)} >> ${failure} (${duration}ms)`,
);
});
worker.on("error", (error, queue, job) => {
console.log(`error ${queue} ${JSON.stringify(job)} >> ${error}`);
});
worker.on("pause", () => {
console.log("worker paused");
});
scheduler.on("start", () => {
console.log("scheduler started");
});
scheduler.on("end", () => {
console.log("scheduler ended");
});
scheduler.on("poll", () => {
console.log("scheduler polling");
});
scheduler.on("leader", () => {
console.log("scheduler became leader");
});
scheduler.on("error", (error) => {
console.log(`scheduler error >> ${error}`);
});
scheduler.on("cleanStuckWorker", (workerName, errorPayload, delta) => {
console.log(
`failing ${workerName} (stuck for ${delta}s) and failing job ${errorPayload}`,
);
});
scheduler.on("workingTimestamp", (timestamp) => {
console.log(`scheduler working timestamp ${timestamp}`);
});
scheduler.on("transferredJob", (timestamp, job) => {
console.log(`scheduler enquing job ${timestamp} >> ${JSON.stringify(job)}`);
});
// //////////////////////
// CONNECT TO A QUEUE //
// //////////////////////
const queue = new Queue({ connection: connectionDetails }, jobs);
queue.on("error", function (error) {
console.log(error);
});
await queue.connect();
await queue.enqueue("math", "add", [1, 2]);
await queue.enqueue("math", "add", [1, 2]);
await queue.enqueue("math", "add", [2, 3]);
await queue.enqueueIn(3000, "math", "subtract", [2, 1]);
jobsToComplete = 4;
}
boot();
// and when you are done
// await queue.end()
// await scheduler.end()
// await worker.end()
+
+
+There are 3 main classes in node-resque
: Queue, Worker, and Scheduler
error
queue.
+multiWorker
in Node Resque which will run many workers at once for you (see below).queue.enqueueIn
or queue.enqueueAt
) should be processed, but it performs some other jobs like checking for 'stuck' workers and general cluster cleanup.
+node-resque
can not guarantee when a job is going to be executed, only when it will become available for execution (added to a Queue).new queue
requires only the "queue" variable to be set. If you intend to run plugins with beforeEnqueue
or afterEnqueue
hooks, you should also pass the jobs
object to it.new worker
has some additional options:options = {
looping: true,
timeout: 5000,
queues: "*",
name: os.hostname() + ":" + process.pid,
};
+
+
+Note that when using "*"
queue:
The configuration hash passed to new NodeResque.Worker
, new NodeResque.Scheduler
or new NodeResque.Queue
can also take a connection
option.
const connectionDetails = {
pkg: "ioredis",
host: "127.0.0.1",
password: "",
port: 6379,
database: 0,
namespace: "resque", // Also allow array of strings
};
const worker = new NodeResque.Worker(
{ connection: connectionDetails, queues: "math" },
jobs,
);
worker.on("error", (error) => {
// handler errors
});
await worker.connect();
worker.start();
// and when you are done
// await worker.end()
+
+
+You can also pass redis client directly.
+// assume you already initialized redis client before
// the "redis" key can be IORedis.Redis or IORedis.Cluster instance
const redisClient = new Redis();
const connectionDetails = { redis: redisClient };
// or
const redisCluster = new Cluster();
const connectionDetails = { redis: redisCluster };
const worker = new NodeResque.Worker(
{ connection: connectionDetails, queues: "math" },
jobs,
);
worker.on("error", (error) => {
// handler errors
});
await worker.connect();
worker.start();
// and when you are done
await worker.end();
+
+
+await worker.end()
, await queue.end()
and await scheduler.end()
before shutting down your application if you want to properly clear your worker status from resque.keyPrefix
if you are using the ioredis
(default) redis driver in this project (see https://github.com/actionhero/node-resque/issues/245 for more information.)beforeEnqueue
or afterEnqueue
, be sure to pass the jobs
argument to the new NodeResque.Queue()
constructorfailed
queue. You can then inspect these jobs, write a plugin to manage them, move them back to the normal queues, etc. Failure behavior by default is just to enter the failed
queue, but there are many options. Check out these examples from the ruby ecosystem for inspiration:
+
+hostname:pid+unique_id
. For example:If you want to learn more about running Node-Resque with docker, please view the examples here: https://github.com/actionhero/node-resque/tree/master/examples/docker
+const name = os.hostname() + ":" + process.pid + "+" + counter;
const worker = new NodeResque.Worker(
{ connection: connectionDetails, queues: "math", name: name },
jobs,
);
+
+
+DO NOT USE THIS IN PRODUCTION. In tests or special cases, you may want to process/work a job in-line. To do so, you can use worker.performInline(jobName, arguments, callback)
. If you are planning on running a job via #performInline, this worker should also not be started, nor should be using event emitters to monitor this worker. This method will also not write to redis at all, including logging errors, modify resque's stats, etc.
const queue = new NodeResque.Queue({ connection: connectionDetails, jobs });
await queue.connect();
+
+
+API documentation for the main methods you will be using to enqueue jobs to be worked can be found @ node-resque.actionherojs.com.
+From time to time, your jobs/workers may fail. Resque workers will move failed jobs to a special failed
queue which will store the original arguments of your job, the failing stack trace, and additional metadata.
You can work with these failed jobs with the following methods:
+let failedCount = await queue.failedCount()
failedCount
is the number of jobs in the failed queuelet failedJobs = await queue.failed(start, stop)
failedJobs
is an array listing the data of the failed jobs. Each element looks like:
+{"worker": "host:pid", "queue": "test_queue", "payload": {"class":"slowJob", "queue":"test_queue", "args":[null]}, "exception": "TypeError", "error": "MyImport is not a function", "backtrace": [' at Worker.perform (/path/to/worker:111:24)', ' at <anonymous>'], "failed_at": "Fri Dec 12 2014 14:01:16 GMT-0800 (PST)"}
await queue.failed(0, -1)
We use a try/catch pattern to catch errors in your jobs. If any job throws an +uncaught exception, it will be caught, and the job's payload moved to the error +queue for inspection. +Do not use domain, process.on("exit"), or any other method +of "catching" a process crash.
+The error payload looks like:
+{ worker: 'busted-worker-3',
queue: 'busted-queue',
payload: { class: 'busted_job', queue: 'busted-queue', args: [ 1, 2, 3 ] },
exception: 'ERROR_NAME',
error: 'I broke',
failed_at: 'Sun Apr 26 2015 14:00:44 GMT+0100 (BST)' }
+
+
+await queue.removeFailed(failedJob)
failedJob
is an expanded node object representing the failed job, retrieved via queue.failed
await queue.retryAndRemoveFailed(failedJob)
failedJob
is an expanded node object representing the failed job, retrieved via queue.failed
By default, the scheduler will check for workers which haven't pinged redis in 60 minutes. If this happens, we will assume the process crashed, and remove it from redis. If this worker was working on a job, we will place it in the failed queue for later inspection. Every worker has a timer running in which it then updates a key in redis every timeout
(default: 5 seconds). If your job is slow, but async, there should be no problem. However, if your job consumes 100% of the CPU of the process, this timer might not fire.
To modify the 60 minute check, change stuckWorkerTimeout
when configuring your scheduler, ie:
const scheduler = new NodeResque.Scheduler({
stuckWorkerTimeout: (1000 * 60 * 60) // 1 hour, in ms
connection: connectionDetails
})
+
+
+Set your scheduler's stuckWorkerTimeout = false
to disable this behavior.
const scheduler = new NodeResque.Scheduler({
stuckWorkerTimeout: false // will not fail jobs which haven't pinged redis
connection: connectionDetails
})
+
+
+Sometimes a worker crashes is a severe way, and it doesn't get the time/chance to notify redis that it is leaving the pool (this happens all the time on PAAS providers like Heroku). When this happens, you will not only need to extract the job from the now-zombie worker's "working on" status, but also remove the stuck worker. To aid you in these edge cases, await queue.cleanOldWorkers(age)
is available.
Because there are no 'heartbeats' in resque, it is impossible for the application to know if a worker has been working on a long job or it is dead. You are required to provide an "age" for how long a worker has been "working", and all those older than that age will be removed, and the job they are working on moved to the error queue (where you can then use queue.retryAndRemoveFailed
) to re-enqueue the job.
If you know the name of a worker that should be removed, you can also call await queue.forceCleanWorker(workerName)
directly, and that will also remove the worker and move any job it was working on into the error queue. This method will still proceed for workers which are only partially in redis, indicting a previous connection failure. In this case, the job which the worker was working on is irrecoverably lost.
You may want to use node-resque to schedule jobs every minute/hour/day, like a distributed CRON system. There are a number of excellent node packages to help you with this, like node-schedule and node-cron. Node-resque makes it possible for you to use the package of your choice to schedule jobs with.
+Assuming you are running node-resque across multiple machines, you will need to ensure that only one of your processes is actually scheduling the jobs. To help you with this, you can inspect which of the scheduler processes is currently acting as leader, and flag only the master scheduler process to run the schedule. A full example can be found at /examples/scheduledJobs.ts, but the relevant section is:
+const NodeResque = require("node-resque");
const schedule = require("node-schedule");
const queue = new NodeResque.Queue({ connection: connectionDetails }, jobs);
const scheduler = new NodeResque.Scheduler({ connection: connectionDetails });
await scheduler.connect();
scheduler.start();
schedule.scheduleJob("10,20,30,40,50 * * * * *", async () => {
// do this job every 10 seconds, CRON style
// we want to ensure that only one instance of this job is scheduled in our environment at once,
// no matter how many schedulers we have running
if (scheduler.leader) {
console.log(">>> enqueuing a job");
await queue.enqueue("time", "ticktock", new Date().toString());
}
});
+
+
+Just like ruby's resque, you can write worker plugins. They look like this. The 4 hooks you have are beforeEnqueue
, afterEnqueue
, beforePerform
, and afterPerform
. Plugins are classes
which extend NodeResque.Plugin
const { Plugin } = require("node-resque");
class MyPlugin extends Plugin {
constructor(...args) {
// @ts-ignore
super(...args);
this.name = "MyPlugin";
}
beforeEnqueue() {
// console.log("** beforeEnqueue")
return true; // should the job be enqueued?
}
afterEnqueue() {
// console.log("** afterEnqueue")
}
beforePerform() {
// console.log("** beforePerform")
return true; // should the job be run?
}
afterPerform() {
// console.log("** afterPerform")
}
}
+
+
+And then your plugin can be invoked within a job like this:
+const jobs = {
add: {
plugins: [MyPlugin],
pluginOptions: {
MyPlugin: { thing: "stuff" },
},
perform: (a, b) => {
let answer = a + b;
return answer;
},
},
};
+
+
+notes
+true
or false
on the before hooks. true
indicates that the action should continue, and false
prevents it. This is called toRun
.this.worker.error
in your plugin. If this.worker.error
is null, no error will be logged in the resque error queue.src/plugins/*
directory. You can write your own and include it like this:const jobs = {
add: {
plugins: [require("Myplugin").Myplugin],
pluginOptions: {
MyPlugin: { thing: "stuff" },
},
perform: (a, b) => {
let answer = a + b;
return answer;
},
},
};
+
+
+The plugins which are included with this package are:
+DelayQueueLock
+JobLock
+QueueLock
+Retry
+node-resque
provides a wrapper around the Worker
class which will auto-scale the number of resque workers. This will process more than one job at a time as long as there is idle CPU within the event loop. For example, if you have a slow job that sends email via SMTP (with low overhead), we can process many jobs at a time, but if you have a math-heavy operation, we'll stick to 1. The MultiWorker
handles this by spawning more and more node-resque workers and managing the pool.
const NodeResque = require("node-resque");
const connectionDetails = {
pkg: "ioredis",
host: "127.0.0.1",
password: "",
};
const multiWorker = new NodeResque.MultiWorker(
{
connection: connectionDetails,
queues: ["slowQueue"],
minTaskProcessors: 1,
maxTaskProcessors: 100,
checkTimeout: 1000,
maxEventLoopDelay: 10,
},
jobs,
);
// normal worker emitters
multiWorker.on("start", (workerId) => {
console.log("worker[" + workerId + "] started");
});
multiWorker.on("end", (workerId) => {
console.log("worker[" + workerId + "] ended");
});
multiWorker.on("cleaning_worker", (workerId, worker, pid) => {
console.log("cleaning old worker " + worker);
});
multiWorker.on("poll", (workerId, queue) => {
console.log("worker[" + workerId + "] polling " + queue);
});
multiWorker.on("ping", (workerId, time) => {
console.log("worker[" + workerId + "] check in @ " + time);
});
multiWorker.on("job", (workerId, queue, job) => {
console.log(
"worker[" + workerId + "] working job " + queue + " " + JSON.stringify(job),
);
});
multiWorker.on("reEnqueue", (workerId, queue, job, plugin) => {
console.log(
"worker[" +
workerId +
"] reEnqueue job (" +
plugin +
") " +
queue +
" " +
JSON.stringify(job),
);
});
multiWorker.on("success", (workerId, queue, job, result) => {
console.log(
"worker[" +
workerId +
"] job success " +
queue +
" " +
JSON.stringify(job) +
" >> " +
result,
);
});
multiWorker.on("failure", (workerId, queue, job, failure) => {
console.log(
"worker[" +
workerId +
"] job failure " +
queue +
" " +
JSON.stringify(job) +
" >> " +
failure,
);
});
multiWorker.on("error", (workerId, queue, job, error) => {
console.log(
"worker[" +
workerId +
"] error " +
queue +
" " +
JSON.stringify(job) +
" >> " +
error,
);
});
multiWorker.on("pause", (workerId) => {
console.log("worker[" + workerId + "] paused");
});
multiWorker.on("multiWorkerAction", (verb, delay) => {
console.log(
"*** checked for worker status: " +
verb +
" (event loop delay: " +
delay +
"ms)",
);
});
multiWorker.start();
+
+
+The Options available for the multiWorker are:
+connection
: The redis configuration options (same as worker)queues
: Array of ordered queue names (or *
) (same as worker)minTaskProcessors
: The minimum number of workers to spawn under this multiWorker, even if there is no work to do. You need at least one, or no work will ever be processed or checkedmaxTaskProcessors
: The maximum number of workers to spawn under this multiWorker, even if the queues are long and there is available CPU (the event loop isn't entirely blocked) to this node process.checkTimeout
: How often to check if the event loop is blocked (in ms) (for adding or removing multiWorker children),maxEventLoopDelay
: How long the event loop has to be delayed before considering it blocked (in ms),This package was featured heavily in this presentation I gave about background jobs + node.js. It contains more examples!
+
Value:
+Symbol.for('nodejs.rejection')
See how to write a custom
+rejection handler
.