Skip to content

Instantly share code, notes, and snippets.

@night-fury-rider
Last active May 16, 2026 05:53
Show Gist options
  • Select an option

  • Save night-fury-rider/f81c56c2e29ea5a3a1da410d30904fee to your computer and use it in GitHub Desktop.

Select an option

Save night-fury-rider/f81c56c2e29ea5a3a1da410d30904fee to your computer and use it in GitHub Desktop.
Design Pattern - Observer
class Observable {
#observers = new Set();
subscribe(observer) {
// Only support function as callback
if (typeof observer !== "function") {
throw new TypeError("Observer must be a function");
}
this.#observers.add(observer);
return () => {
this.unsubscribe(observer);
};
}
unsubscribe(observer) {
this.#observers.delete(observer);
}
async notify(data) {
const observers = this.#observers;
if (observers.size === 0) {
return;
}
const observersSnapshot = [...observers];
const results = await Promise.allSettled(
observersSnapshot.map((observer) => observer(data)),
);
for (let i = 0; i < results.length; i++) {
if (results[i].status === "rejected") {
console.error(`Observer #${i} threw an error:`, results[i].reason);
}
}
}
clearAll() {
this.#observers.clear();
}
}
class Stock extends Observable {
#name;
#price;
constructor(name, price) {
super();
this.#name = name;
this.#price = price;
}
async changePrice(newPrice) {
this.#price = newPrice;
await this.notify({
name: this.#name,
price: this.#price,
});
}
}
class Investor {
#name;
constructor(name) {
this.#name = name;
}
updatePortfolio(stock) {
console.log(
`${this.#name} has updated portfolio since ${stock.name} has been changed to ${stock.price}`,
);
}
}
const sbiStock = new Stock("SBI", 1500);
const investor1 = new Investor("Sagar");
const investor2 = new Investor("Sarita");
const unsubscribeInvestor1 = sbiStock.subscribe(
investor1.updatePortfolio.bind(investor1),
);
const unsubscribeInvestor2 = sbiStock.subscribe(
investor2.updatePortfolio.bind(investor2),
);
await sbiStock.changePrice(2000); // Both investors get notified
unsubscribeInvestor2(); // Investor 2 unsubscribes
setTimeout(async () => {
await sbiStock.changePrice(2500); // Only investor1 gets notified
}, 2 * 1000);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment