BACK
Use casesComponent VM — один поток для шаблона
Use cases · 40

Component VM — один поток для шаблона

Паттерн

Шаблон компонента получает один vm$ — Observable, который содержит всё нужное для рендера: user, route, permissions, loading. Один vm$ | async в шаблоне вместо четырёх async pipe.

Какую проблему решаем

Если шаблон подписан на 4 разных Observable через async pipe — Angular подпишется 4 раза на cold sources (4 HTTP-запроса!). А ещё промежуточные состояния — user уже пришёл, permissions ещё null — шаблон будет рендерить полу-готовый интерфейс.

Операторы и зачем они нужны

  • combineLatest — собирает все источники в один поток. Каждое изменение любого — новый VM.
  • map — вычисляет derived state (canAdmin = permissions.includes('admin')) один раз в одном месте.
  • shareReplay({ bufferSize: 1, refCount: true }) — несколько подписчиков получают один и тот же VM. Late subscriber видит последнее состояние сразу.

Подводные камни

  • Без shareReplay два vm$ | async в одном шаблоне создадут две подписки на upstream. Двойные HTTP-запросы.
  • Не смешивайте imperative-поля и vm$. Один источник истины — vm$.
  • Если какой-то source не имеет initial value, combineLatest молчит до первого эмита каждого. Используйте startWith или BehaviorSubject.

Что в итоге получаем

Шаблон рендерит один согласованный объект. Никаких промежуточных «полу-загруженных» рендеров.

script.ts // TypeScript
CONSOLE · Console Output
Нажмите на запуск, чтобы увидеть результат...