What is the observer pattern in JavaScript?
The observer pattern lets a subject keep a list of observers and notify them automatically whenever its state changes.
Subject — holds data and a list of subscribers; offers subscribe and unsubscribe.
Observers — functions or objects that react when notified.
Everywhere: DOM event listeners, state managers, and Node's EventEmitter are all forms of this pattern.
// Simple EventEmitter implementation
class EventEmitter {
constructor() {
this.listeners = {};
}
on(event, callback) {
(this.listeners[event] ||= []).push(callback);
return () => this.off(event, callback); // Return unsubscribe function
}
off(event, callback) {
this.listeners[event] = this.listeners[event]?.filter(cb => cb !== callback);
}
emit(event, ...args) {
this.listeners[event]?.forEach(cb => cb(...args));
}
once(event, callback) {
const wrapper = (...args) => {
callback(...args);
this.off(event, wrapper);
};
this.on(event, wrapper);
}
}
// Usage
const bus = new EventEmitter();
const unsub = bus.on('userLogin', (user) => {
console.log(`${user.name} logged in`);
});
bus.on('userLogin', (user) => {
analytics.track('login', user);
});
bus.emit('userLogin', { name: 'John', id: 1 });
// Both handlers fire
unsub(); // Unsubscribe first handlerEventEmitter stores listener arrays by event name. on registers a listener and returns an unsubscribe function. emit calls all listeners for the event. once auto-removes after first call. The ||= operator lazily creates the array.
Multiple independent listeners react to the same event — decoupled communication.
Implement a basic EventEmitter (on, off, emit, once) — this is a common coding interview question. The unsubscribe function returned from on() is a clean pattern.
Know that DOM events, Node.js EventEmitter, and Redux all implement this pattern.