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
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 a fake analytics provider