Наблюдателей удобно хранить в Set, уведомляя их в setter при присваивании нового объекта.
Реализуйте на TypeScript класс по паттерну «Наблюдатель»: он хранит данные в объекте, позволяет подписываться и отписываться через subscribe/unsubscribe и уведомляет подписчиков при изменении данных через присваивание. Нужны getter и setter; начальное значение по умолчанию — пустой объект.
Наблюдателей удобно хранить в Set, уведомляя их в setter при присваивании нового объекта.
Короткий ответ
Что ответить на собеседовании
Подробный разбор
Ответ с пояснениями
Наблюдателей удобно хранить в Set, уведомляя их в setter при присваивании нового объекта.
Контракт ниже уведомляет при store.data = next, но не при вложенной мутации store.data.x = 1. Подписка не вызывает callback сразу; повторное присваивание той же ссылки пропускается.
type Data = Record<string, unknown>;
type Listener = (next: Data, previous: Data) => void;
class ObservableStore {
private value: Data;
private listeners = new Set<Listener>();
constructor(initial: Data = {}) { this.value = initial; }
get data(): Data { return this.value; }
set data(next: Data) {
if (Object.is(next, this.value)) return;
const previous = this.value;
this.value = next;
const errors: unknown[] = [];
for (const listener of [...this.listeners]) {
try { listener(next, previous); }
catch (error) { errors.push(error); }
}
if (errors.length) throw new AggregateError(errors, 'Ошибки наблюдателей');
}
subscribe(listener: Listener): () => void {
this.listeners.add(listener);
return () => this.unsubscribe(listener);
}
unsubscribe(listener: Listener): void { this.listeners.delete(listener); }
}
Используется ES2021 для AggregateError. Снимок подписчиков сохраняет состав текущего обхода; ошибки не мешают вызвать остальных. Для уведомлений о каждой вложенной записи потребуются отдельные методы обновления или Proxy.