Hiprup

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 handler

EventEmitter 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.

What is the observer pattern in JavaScript? | Hiprup