All questions

Async Event Emitter

Premium

Async Event Emitter

Node's EventEmitter is fire-and-forget: emit calls every listener synchronously and returns, ignoring anything a listener does asynchronously. That breaks down the moment listeners do real work — writing to a DB, calling an API, flushing a queue — and you need to know when they're all done, or run them one-at-a-time to avoid a stampede. An async event emitter makes emit return a promise that awaits its listeners, with a choice of serial or parallel dispatch.

Implement eventEmitterAsync() with on, once, off, emit, emitParallel, and listenerCount.

Signature

function eventEmitterAsync() {
  return { on, once, off, emit, emitParallel, listenerCount };
}

Examples

const em = eventEmitterAsync();
em.on('save', async (row) => { await db.insert(row); });
em.on('save', async (row) => { await audit(row); });

await em.emit('save', row);        // serial: insert finishes, THEN audit
await em.emitParallel('save', row); // both start at once, awaits both
const off = em.on('tick', fn);
em.once('ready', init); // auto-removed after the first emit
off();                  // unsubscribe

Notes

  • emit awaits, serially — call listeners in registration order, awaiting each before the next; resolve to the array of their return values.
  • emitParallel — start every listener at once and Promise.all them.
  • Errors — serial emit rejects on the first throwing listener and skips the rest; emitParallel rejects if any listener rejects.
  • once and unsubscribeonce fires a listener a single time (removed before it runs); on/once both return an unsubscribe. Snapshot the listener list in emit so on/off mid-dispatch don't disturb the round.

Unlock the solution & editor

  • Runnable editor + tests

    Solve in the browser with instant Jest feedback.

  • Detailed solutions

    Walkthroughs, edge cases, and complexity notes.

  • Multi-framework variants

    React, Vue, Vanilla, Angular — same question, different stacks.

Upgrade to Premium