Use cases/Load state machine — idle/loading/success/error
Use cases · 43 操
Load state machine — idle/loading/success/error
Паттерн
Каждый async-запрос проходит через явные состояния: loading → success(data) или error(message). Это discriminated union — типизированная state machine, а не три раздельных boolean.
Какую проблему решаем
Раздельные поля isLoading, data, error легко рассогласовать. После failure кто-то забыл сбросить data, и UI показывает старые данные с error-баннером сверху. Невозможные комбинации флагов плодятся как сорняки.
Операторы и зачем они нужны
startWith({kind: 'loading'}) — сразу эмитим loading-состояние, ДО ответа.
map(data => ({kind: 'success', data})) — успешный ответ становится success-state.
catchError(error => of({kind: 'error', error})) — failure становится error-state, БЕЗ падения outer stream.
Подводные камни
tap с ручными флагами this.isLoading=true/false — труднее тестировать, чем state-as-data.
catchError снаружи trigger-stream — одна ошибка остановит все будущие reload. Ставьте ВНУТРИ switchMap.
Не смешивайте idle и loading. idle = «запроса ещё не было». loading = «запрос летит». Это разные состояния.
Что в итоге получаем
UI получает один типизированный state и рендерит его через switch. Невозможных комбинаций больше нет.