EventEmitter is the class in Node's events module that lets an object announce named events. You register a listener with emitter.on('name', fn) and trigger it with emitter.emit('name', ...args); every listener for that name runs, in the order it was added, with the arguments you passed. HTTP servers, streams and process are all EventEmitters, so the same few methods work everywhere in Node.
Both listeners run between before emit and after emit: emit calls them synchronously and returns only when they are done. Swap the two shop.on calls and the two middle lines swap too.
on, once and off
on keeps a listener until you remove it, once removes it after the first call, and off (the same as removeListener) removes one. To remove a listener you need the same function you added, so name it instead of passing an arrow function inline.
first open ever prints once, after Ada. Once logOpen is removed nothing is listening, so the last emit returns false; door.removeAllListeners('open') would have cleared both listeners in one call.
| Method | Does |
|---|---|
on(name, fn), addListener | Calls fn on every emit |
once(name, fn) | Calls fn on the next emit only |
prependListener(name, fn) | Like on, but runs before the existing listeners |
off(name, fn), removeListener | Removes that function |
emit(name, ...args) | Calls the listeners, returns true if there were any |
listenerCount(name) | How many listeners the event has |
The error event
'error' is special. If you emit it and nobody listens, emit throws the error, and in a real program an uncaught throw crashes the process. Always add an 'error' listener to emitters that can fail, such as streams and servers.
Without a listener, emit throws and the catch gets it; with the listener added, the same emit just calls it and the program carries on. Any other event name with no listeners is silently ignored.
Extend EventEmitter in your own class
The usual way to use it is to make your class extend EventEmitter, call super() in the constructor and this.emit when something happens. Callers then subscribe to your object like to any Node object.
It prints 25%, 50%, 75%, 100% and then photo.png uploaded. Move up.start() above the two up.on lines and nothing prints: the events fire before anyone listens.
The same trap applies to emitting from a constructor. Libraries that must emit right away wrap the call in process.nextTick, which runs after the caller's on lines (see the event loop page).
Wait for an event with events.once
events.once(emitter, name) returns a promise that resolves with the event's arguments, as an array, the next time it is emitted. It turns a one-time event into something you can await, and it rejects if the emitter emits 'error' first.
The await pauses until the timer emits ready, then the array destructures into the two arguments. For an event that fires many times, events.on(emitter, name) gives an async iterator you can loop over with for await.
Common mistakes
Adding a listener inside a function that runs often. Calling on in every request handler stacks up listeners and memory. Add it once, or use once.
Removing an inline function. off('data', () => ...) removes nothing, because that arrow function is a new one. Keep a reference to the function you added.
Expecting listeners to run later. emit is synchronous, so a slow listener holds up the code that emitted. Marking the listener async does not help, because its code still runs on the same thread until the first await. Split heavy work into pieces with setImmediate between them, or move it to a worker thread.
Frequently Asked Questions
Is EventEmitter asynchronous?
No. emit calls every listener right away, one after another, and returns when the last one is done. Code inside a listener can start async work, but the listener itself is called synchronously.
What does the MaxListenersExceededWarning mean?
Node warns when more than 10 listeners are added for one event, because that often means a listener is added on every request and never removed. Remove the extra listeners, or call emitter.setMaxListeners(n) if you really need more.
What does emit return?
true if the event had at least one listener, false if nobody was listening. It does not return what the listeners return.
Which Node.js objects are EventEmitters?
Most of Node's core objects: HTTP servers, requests and responses, streams, sockets, process and readline interfaces. That is why they all share on, once and off.