All topics
Patternsintermediate

Observer Pattern and Pub/Sub

A pattern where one or more 'observers' subscribe to notifications from a 'subject,' decoupling the code that triggers events from the code that reacts to them.

The Observer pattern (and its close cousin, the publish/subscribe or 'pub/sub' pattern) defines a one-to-many relationship where a subject maintains a list of dependent observers and automatically notifies all of them whenever its own state changes, without needing to know anything specific about who those observers are or what they'll do with the notification. This is one of the most practically important patterns in JavaScript because it's the conceptual foundation underneath DOM event listeners, custom event systems, and reactive state libraries.

The Observer pattern is like a magazine subscription service: the publisher (subject) doesn't need to personally know each individual subscriber's reading habits or preferences — it just mails out the next issue to everyone currently on its subscriber list, and subscribers can join or cancel their subscription independently without the publisher needing to change anything about how it prints and distributes issues.

Key Concepts

1
In the classic Observer pattern, observers register themselves directly with a specific subject instance (subject.subscribe(observer)), and the subject holds a direct reference to each of its observers, calling a known method on each of them (like .update()) whenever a relevant change occurs. Pub/sub is a related but distinct variant that adds a layer of indirection: publishers and subscribers don't reference each other directly at all — they communicate only through a shared event bus/broker, publishing to or subscribing on named 'topics' or event types, with the broker responsible for routing notifications to whichever subscribers happen to be registered for that topic at the time.
subject.subscribe(observer).update()
2
This extra indirection in pub/sub means publishers and subscribers can be added, removed, or replaced independently without either side needing to know the other exists at all — genuinely useful for decoupling large parts of an application (like separate feature modules communicating through a shared event bus rather than importing and calling each other directly), at the cost of making the overall flow of 'who reacts to what' somewhat harder to trace statically through the code, since the connections are established dynamically at runtime rather than being visible as direct function calls or imports.
3
DOM events (addEventListener) are effectively a built-in observer-pattern implementation provided by the browser itself, and many state-management libraries (Redux's subscribe mechanism, RxJS observables) are built on the same underlying idea, just with additional structure (like RxJS's operators for transforming event streams) layered on top of the core notify-all-subscribers mechanic.
addEventListener