Observer Pattern
Use observables to notify subscribers when an event occurs
Overview
With the observer pattern, we have:
- An observable object, which can be observed by subscribers in order to notify them.
- Subscribers, which can subscribe to and get notified by the observable object.
For example, we can add the logger
as a subscriber to the observable.
When the notify
method is invoked on the observable, all subscribers get invoked and (optionally) pass the data from the notifier to them.
Implementation
We can export a singleton Observer object, which contains a notify
, subscribe
, and unsubscribe
method.
const observers = [];
export default Object.freeze({
notify: (data) => observers.forEach((observer) => observer(data)),
subscribe: (func) => observers.push(func),
unsubscribe: (func) => {
[...observers].forEach((observer, index) => {
if (observer === func) {
observers.splice(index, 1);
}
});
},
});
We can use this observable throughout the entire application, making it possible to subscribe functions to the observable
import Observable from "./observable";
function logger(data) {
console.log(`${Date.now()} ${data}`);
}
Observable.subscribe(logger);
and notify all subscribers based on certain events.
import Observable from "./observable";
document.getElementById("my-button").addEventListener("click", () => {
Observable.notify("Clicked!"); // Notifies all subscribed observers
});
Tradeoffs
Separation of Concerns: The observer objects aren't tightly coupled to the observable object, and can be (de)coupled at any time. The observable object is responsible for monitoring the events, while the observers simply handle the received data.
Decreased performance: Notifying all subscribers might take a significant amount of time if the observer handling becomes too complex, or if there are too many subscibers to notify.
Exercise
The two buttons in our application both send events to a fake analytics provider.
Challenge
Create an observer to which the buttons can subscribe. When a user clicks on a button, this event should get sent to the fake analytics provider.