Ответ
Обычно беру готовый из библиотеки, например RxJS или MobX, так как они уже покрывают edge cases, имеют хорошую документацию и тесты. Но если задача простая и специфичная, могу написать минимальную реализацию:
class Observer {
constructor() {
this.subscribers = [];
}
subscribe(fn) {
this.subscribers.push(fn);
return () => this.unsubscribe(fn);
}
unsubscribe(fn) {
this.subscribers = this.subscribers.filter(sub => sub !== fn);
}
notify(data) {
this.subscribers.forEach(fn => fn(data));
}
}
Главное - понимать принципы работы паттерна, даже если используешь готовое решение.