emitter.emit()

Call every listener registered for an event synchronously, passing along the given arguments.

Signature
emitter.emit(eventName[, ...args])
  • Added in Node.js v0.1.26

Parameters

ParameterTypeDescription
$eventName<string> | <symbol>The name of the event to emit.
$...argsoptional<any>Any number of arguments, passed positionally to every listener.

Return value

<boolean>true if the event had at least one registered listener, false otherwise.

Errors

Rethrows anything a listener throws. Emitting 'error' with no 'error' listener throws the emitted error (or an ERR_UNHANDLED_ERROR if the payload is not an Error).

emit() synchronously invokes every listener registered for eventName, in registration order, forwarding all extra arguments. It returns true when at least one listener existed and false when the event fell on the floor.

When to reach for it

Call it from the producing side of your abstraction — a parser announcing a row, a job announcing progress. The boolean return is worth reading when a dropped event matters: if (!this.emit('error', err)) throw err; is the idiom for "nobody is listening, so escalate".

What trips people up

It blocks. There is no queue and no microtask hop. A listener that spends 200 ms in a loop makes your emit() call take 200 ms, and an exception thrown by any listener propagates straight back to the caller of emit(), skipping the listeners registered after it.

Listeners cannot return values to the emitter — the return type is a boolean about registration, not about success. And an async listener returns a promise that emit() simply discards, so failures inside it become unhandled rejections unless the emitter was constructed with captureRejections: true.

Example

Try it yourself
Loading editor…
Press Run to execute the code.

When to use it

  • Announce each parsed record from a CSV reader so consumers can process them as they arrive
  • Escalate an error by throwing it when emit('error', err) returns false
  • Broadcast a config change to every subscribed module in one call

Frequently asked questions

Is emitter.emit() synchronous in Node.js?

Yes, fully synchronous. Every listener runs to completion before emit() returns, with no event-loop tick in between. Wrap the call in setImmediate() or process.nextTick() if you need callers to be able to subscribe first.

What does emitter.emit() return?

A boolean: true if at least one listener was registered for that event name, false if none were. It reflects registration only — it does not indicate whether the listeners succeeded, and it never returns a listener's value.

How do I pass multiple arguments to an event listener?

Pass them as extra arguments after the event name: emitter.emit('order', id, total). Each listener receives them positionally. Many codebases prefer a single object payload instead, so adding a field later does not break listener signatures.

More examples

emit() is synchronous and blocking

Output is 1, 2, 3, 4, then the deferred listener body. Nothing about emit() involves the event loop — the listener runs inline, so numbers 1 through 3 are strictly ordered. Wrapping the emit in setImmediate() is the standard way to give callers a chance to subscribe before the first event fires.

Example · javascript
const { EventEmitter } = require('node:events');
const bus = new EventEmitter();

bus.on('work', () => console.log('2: listener body'));

console.log('1: before emit');
bus.emit('work');
console.log('3: after emit');

// To hand control back to the event loop first, defer the emit:
setImmediate(() => bus.emit('work'));
console.log('4: emit deferred');

A throwing listener aborts the rest of the emit

The exception from listener two propagates out of emit(), so listener three never runs and the emitter is left in a half-notified state. If subscribers are untrusted or independent, wrap each listener body in its own try/catch rather than relying on emit() to isolate them.

Example · javascript
const { EventEmitter } = require('node:events');
const bus = new EventEmitter();

bus.on('save', () => console.log('first listener ran'));
bus.on('save', () => { throw new Error('second listener failed'); });
bus.on('save', () => console.log('third listener - never reached'));

try {
  bus.emit('save');
} catch (err) {
  console.log('emit rethrew:', err.message);
}

console.log('listeners still registered:', bus.listenerCount('save'));

Using the return value to escalate errors

The first uploader has an 'error' listener, so emit() returns true and the error is handled. The second has none, emit() returns false, and the explicit throw surfaces the failure instead of losing it. This is the same pattern core streams use.

Example · javascript
const { EventEmitter } = require('node:events');

class Uploader extends EventEmitter {
  fail(reason) {
    const err = new Error(reason);
    // If nobody subscribed, do not swallow the failure.
    if (!this.emit('error', err)) throw err;
  }
}

const watched = new Uploader();
watched.on('error', (err) => console.log('handled:', err.message));
watched.fail('disk full');

try {
  new Uploader().fail('disk full');
} catch (err) {
  console.log('escalated:', err.message);
}

Discussion

  • Be the first to comment on this lesson.