emitter.listenerCount()
Count how many listeners are registered for an event, optionally for one specific function.
emitter.listenerCount(eventName[, listener])- Added in Node.js v3.2.0
Parameters
| Parameter | Type | Description |
|---|---|---|
$eventName | <string> | <symbol> | The name of the event being listened for. |
$listeneroptional | <Function> | A specific handler function to count occurrences of. |
Return value
<integer>The number of listeners for eventName, or how many times listener appears in that event's listener list when listener is given.
Errors
Does not throw for unknown event names; an event nobody subscribed to returns 0.
Changelog
- PHP v19.8.0, v18.16.0Added the listener argument. On earlier versions the method ignores a second argument and always returns the total count for the event.
listenerCount() returns how many listeners an event currently has. Pass a second argument and it instead returns how many times that specific function appears in the list — the fastest way to prove a duplicate subscription.
When to reach for it
It is mostly a diagnostic. Reach for it when a handler fires twice and you need to know whether the bug is a duplicate on() or a duplicate emit(). It is also useful in tests ("assert the component unsubscribed on teardown") and in cleanup code that must verify the count returned to its baseline.
For the "is anyone listening?" check inside production code, prefer the boolean that emit() already returns rather than a count comparison — it is one call instead of two and cannot go stale.
What trips people up
The count includes once() registrations, which vanish the moment they fire, so a count captured before an emit will not match one captured after. The listener argument is recent — on Node 18.15 and earlier it is ignored and you get the total instead, which reads as a passing check when it is not.
Example
When to use it
- Prove a handler is registered twice when it fires twice per event
- Assert in a test that teardown removed every listener it added
- Verify a per-request subscription count returns to baseline after the response closes
Frequently asked questions
How do I check how many listeners an event has in Node.js?
Call emitter.listenerCount(eventName); it returns an integer and returns 0 for events nobody subscribed to. The static events.listenerCount(emitter, eventName) form still exists but has been deprecated since Node 3.2.0 in favour of the instance method.
How can I tell if the same function was added as a listener twice?
Pass it as the second argument: emitter.listenerCount('data', handler) returns how many times that exact function appears. This requires Node 19.8.0 or 18.16.0 and later — older versions ignore the argument and return the event's total.
Does listenerCount() include once() listeners?
Yes, while they are still pending. A once() listener counts as one until it fires, at which point it removes itself and the count drops. Sample the count at a consistent point in the lifecycle if you are comparing before and after.
More examples
once() listeners disappear from the count
The count is 2 before the emit and 1 after, because the once() listener removed itself as it fired. Any leak check that samples listenerCount() at a single point in time can therefore be misled — compare a baseline taken at the same lifecycle stage instead.
const { EventEmitter } = require('node:events');
const bus = new EventEmitter();
bus.on('ready', () => console.log('persistent'));
bus.once('ready', () => console.log('one-shot'));
console.log('before emit:', bus.listenerCount('ready'));
bus.emit('ready');
console.log('after emit:', bus.listenerCount('ready'));A leak assertion in a test
Comparing against a baseline rather than against zero keeps the assertion valid on shared emitters that already carry internal listeners. This pattern catches the most common regression in subscription code: a detach function that closes over the wrong reference and therefore removes nothing.
const test = require('node:test');
const assert = require('node:assert');
const { EventEmitter } = require('node:events');
function attach(bus) {
const onTick = () => {};
bus.on('tick', onTick);
return () => bus.off('tick', onTick);
}
test('detach removes exactly what it added', () => {
const bus = new EventEmitter();
const baseline = bus.listenerCount('tick');
const detach = attach(bus);
assert.strictEqual(bus.listenerCount('tick'), baseline + 1);
detach();
assert.strictEqual(bus.listenerCount('tick'), baseline);
});
Discussion