Skip to content

EventEmitter API Reference

EventEmitter is the backbone of Node's asynchronous architecture Streams , HTTP servers , child processes , and half the Node API inherit from EventEmitter Know this API cold - it shows up everywhere

Module

const EventEmitter = require('events')
const EventEmitter = require('events').EventEmitter  // same thing

Creating an EventEmitter

class MyEmitter extends EventEmitter {}
const emitter = new MyEmitter()

// Or create directly
const emitter = new EventEmitter()

Most Node objects that emit events are EventEmitter subclasses Stream , Server , Socket , Process , Readline , etc.

Methods

emitter.on(eventName, listener)

Adds a listener for the named event

emitter.on('data', (chunk) => {
  console.log('Received:', chunk.length, 'bytes')
})

emitter.on('error', (err) => {
  console.error('Error:', err.message)
})

emitter.addListener(eventName, listener)

Alias for emitter.on()

emitter.addListener('connect', () => console.log('connected'))

emitter.once(eventName, listener)

Adds a one-time listener - fires once then auto-removed

emitter.once('close', () => {
  console.log('This runs only once')
})

// Example: first connection
server.once('connection', () => {
  console.log('First client connected')
})

emitter.emit(eventName[, ...args])

Emits the named event , passing args to listeners Returns true if event had listeners , false otherwise

emitter.emit('data', Buffer.from('hello'))
emitter.emit('error', new Error('something broke'))
emitter.emit('status', 200, 'OK')

emitter.eventNames()

Returns array of event names with registered listeners

emitter.on('data', () => {})
emitter.on('end', () => {})
emitter.once('error', () => {})

console.log(emitter.eventNames())
// [ 'data', 'end', 'error' ]

Returns strings for named events , symbols for symbol-keyed events

emitter.getMaxListeners()

Returns the current max listener count (default 10)

console.log(emitter.getMaxListeners()) // 10

emitter.listenerCount(eventName)

Returns count of listeners for a specific event

emitter.on('data', handler1)
emitter.on('data', handler2)

console.log(emitter.listenerCount('data')) // 2

emitter.listeners(eventName)

Returns a copy of the array of listeners for the named event

emitter.on('data', myHandler)
const listeners = emitter.listeners('data')
console.log(listeners.length) // 1
console.log(listeners[0] === myHandler) // true

emitter.rawListeners(eventName)

Returns a copy of the array of listeners (including wrappers) Unlike listeners() , this returns the raw wrapped functions for once listeners

emitter.once('data', () => console.log('once'))
const raw = emitter.rawListeners('data')
console.log(raw[0].listener) // the original function

Useful for inspecting wrapped listeners - rarely needed

emitter.prependListener(eventName, listener)

Adds listener to the BEGINNING of the listeners array

emitter.on('data', () => console.log('second'))
emitter.prependListener('data', () => console.log('first'))
emitter.emit('data')
// first
// second

emitter.prependOnceListener(eventName, listener)

Adds one-time listener to the BEGINNING of the listeners array

emitter.prependOnceListener('close', () => console.log('runs first once'))

emitter.removeAllListeners([eventName])

Removes all listeners , or all listeners for a specific event

emitter.removeAllListeners()         // removes everything
emitter.removeAllListeners('data')   // removes only 'data' listeners

Be careful - this removes ALL listeners including system ones Prefer removeListener for surgical removal

emitter.removeListener(eventName, listener)

Removes a specific listener (must pass the same function reference)

function onData(chunk) {
  console.log(chunk)
}

emitter.on('data', onData)

// Later...
emitter.removeListener('data', onData)

Anonymous functions can't be removed - keep references if you need to remove later

emitter.setMaxListeners(n)

Changes the max listener warning threshold Set to 0 for unlimited (but think twice)

emitter.setMaxListeners(20)  // warn after 20 listeners
emitter.setMaxListeners(0)   // unlimited (no warning)

The default warning at 10 listeners catches memory leaks If you intentionally need many listeners , set this higher - don't suppress the warning blindly

EventEmitter.defaultMaxListeners

Static property - changes default for ALL EventEmitter instances

EventEmitter.defaultMaxListeners = 50
// Affects ALL emitters created after this line

Use with extreme caution - setMaxListeners per-instance is cleaner

Error Events

emitter.on('error', (err) => {
  console.error('Caught:', err.message)
})

emitter.emit('error', new Error('something broke'))
// Caught: something broke

If an 'error' event is emitted and there's no listener for it , Node throws the error and crashes the process

// CRASHES the process - no error listener
emitter.emit('error', new Error('unhandled'))

Always add an 'error' listener when you create or consume an EventEmitter This is the most common source of "unhandled error" crashes in Node apps

Async Event Patterns

Using async listeners

// Async listeners are supported but catch their errors
emitter.on('data', async (chunk) => {
  // If this throws, the promise rejection is unhandled
  await processChunk(chunk)
})

// Better: catch async errors explicitly
emitter.on('data', async (chunk) => {
  try {
    await processChunk(chunk)
  } catch (err) {
    emitter.emit('error', err)
  }
})

Emitting async results

class AsyncEmitter extends EventEmitter {
  async process(data) {
    try {
      const result = await someAsyncOperation(data)
      this.emit('complete', result)
    } catch (err) {
      this.emit('error', err)
    }
  }
}

EventEmitter with AbortSignal

const ac = new AbortController()

emitter.on('data', (chunk) => {
  if (ac.signal.aborted) return
  console.log(chunk)
})

ac.signal.addEventListener('abort', () => {
  emitter.removeAllListeners()
})

// Cancel all listeners
ac.abort()

Memory Leak Detection

// Node warns if you add more than 10 listeners to one event
for (let i = 0; i < 15; i++) {
  emitter.on('data', () => {})
}
// (node) MaxListenersExceededWarning: Possible EventEmitter memory leak detected.
// 15 data listeners added to [MyEmitter]. Use emitter.setMaxListeners() to increase limit

The warning means you probably forgot to remove listeners - not that 11 listeners is bad

// Common leak pattern
function processData(stream) {
  stream.on('data', (chunk) => {
    // ...
  })
  // Listener is never removed
  // Each call adds another listener
}

Prerequisites