EventEmitter implement Observer/pub-sub pattern — backbone của Node.js internals (streams, http.Server, process đều extend EventEmitter).
- API cơ bản:
.on('event', listener)đăng ký persistent listener,.once('event', listener)tự remove sau lần emit đầu tiên,.emit('event', ...args)kích hoạt đồng bộ tất cả listeners,.off('event', listener)hoặc.removeListener()để unsubscribe. - Memory leak warning: Node.js warn khi > 10 listeners trên cùng event (
MaxListenersExceededWarning) — dùngemitter.setMaxListeners(20)nếu cố ý, hoặc fix leak. - Thường quên
.removeListener()trong component unmount/cleanup → listeners tích lũy. - Error convention: event tên
'error'đặc biệt — nếu emit'error'mà không có listener thì throw uncaughtException crash process. - Practical patterns:
class OrderService extends EventEmitter { async createOrder(data) { const order = await db.save(data); this.emit('order:created', order); } }— services khác lắng nghe event thay vì coupling trực tiếp..once()dùng cho one-time setup:server.once('listening', () => console.log('ready')). - Async listeners: EventEmitter không await async listeners — unhandled promise trong listener → silent failure.
EventEmitter implements the Observer/pub-sub pattern — it's the backbone of Node.js internals (streams, http.Server, and process all extend EventEmitter).
- Core API:
.on('event', listener)registers a persistent listener,.once('event', listener)auto-removes after the first emit,.emit('event', ...args)synchronously triggers all listeners,.off('event', listener)or.removeListener()to unsubscribe. - Memory leak warning: Node.js warns when there are more than 10 listeners on the same event (
MaxListenersExceededWarning) — useemitter.setMaxListeners(20)if intentional, or fix the leak. - The most common leak: forgetting
.removeListener()when a component unmounts/cleans up → listeners accumulate. - Error convention: the
'error'event name is special — emitting'error'with no listener throws an uncaughtException that crashes the process. - Practical patterns:
class OrderService extends EventEmitter { async createOrder(data) { const order = await db.save(data); this.emit('order:created', order); } }— other services listen to events instead of directly coupling..once()for one-time setup:server.once('listening', () => console.log('ready')). - Async listeners: EventEmitter doesn't await async listeners — an unhandled promise in a listener causes silent failure.