Angular
Resource API и httpResource
Сигналы дали реактивное синхронное состояние, но данные обычно приходят асинхронно по сети. Раньше эти два мира сшивали вручную: подписаться на Observable, разложить результат по полям loading, error, value, не забыть отписаться. Resource API стирает шов. resource() и httpResource() сами выполняют асинхронную загрузку и выставляют результат как готовые сигналы value(), status(), error(). А когда меняется реактивный параметр запроса, ресурс сам перезапрашивает данные. Асинхронная загрузка наконец живёт в том же сигнальном мире, что и остальное состояние.
- httpResource: один вызов превращает HTTP-запрос в сигналы данных, загрузки и ошибки, без ручной подписки
- Реактивные параметры: ресурс с params на основе сигнала id сам перезапрашивает данные при смене id в URL
- Состояния загрузки: status() и isLoading() напрямую управляют спиннером и сообщением об ошибке в шаблоне
- Zoneless-приложения: ресурс - естественный источник асинхронных данных, который change detection видит через сигналы
- Master-detail экраны: выбор записи в списке меняет сигнал, и detail-ресурс автоматически подтягивает её данные
Предварительные знания
- Сигналы: signal(), computed(), чтение значения вызовом
- HttpClient и типизированные запросы get/post
- Понятие асинхронной загрузки и состояний loading/error/success
Зачем нужен Resource API
Сигналы реактивны и синхронны: значение всегда доступно сразу. Сетевые данные приходят асинхронно и несут с собой не одно значение, а целое состояние: идёт ли загрузка, есть ли ошибка, пришёл ли результат. Раньше это собирали руками: завести три сигнала, подписаться на Observable, в next записать value, в error записать ошибку, не забыть про отписку. Много шаблонного кода и легко ошибиться.
resource() сам управляет всем жизненным циклом загрузки. Функция params читает реактивные значения (здесь id()), а loader выполняет асинхронную работу и возвращает промис. Ресурс выставляет результат как сигналы value, status, error и обновляет их по ходу загрузки. Ручных подписок и отписок больше нет.
Ключевая особенность: при изменении любого сигнала, прочитанного в params, ресурс автоматически перезапускает loader с новыми параметрами. Смена id() с 1 на 2 сама инициирует новую загрузку, и value() обновится. Это и есть реактивная перезагрузка по параметрам.
Что произойдёт с ресурсом, если изменить сигнал, прочитанный внутри его функции params?
httpResource и его сигналы
httpResource() - специализация resource для самого частого случая: загрузки по HTTP. Вместо ручного loader он сам ходит через HttpClient. На вход - URL или объект запроса (метод, заголовки, тело), на выход - те же сигналы value/status/error. Дженерик задаёт тип данных, как в HttpClient.
| Сигнал ресурса | Что отдаёт | Где применяют |
|---|---|---|
| value() | Данные или undefined, пока их нет | Отображение результата в шаблоне |
| status() | Состояние: idle, loading, resolved, error | Логика по фазе загрузки |
| isLoading() | Булев признак активной загрузки | Показ спиннера |
| error() | Ошибку загрузки или undefined | Сообщение об ошибке, повтор запроса |
URL в httpResource - реактивная функция, а не строка. Передав готовую строку вместо колбэка, ресурс не пересоберёт запрос при смене id. Чтобы перезагрузка по параметру работала, внутри функции должен читаться сигнал: () => `/api/users/${this.id()}`.
В чём преимущество httpResource перед общим resource для загрузки по HTTP?
Resource против subscribe и AsyncPipe
До сигналов асинхронные данные потребляли через Observable: либо ручной subscribe в коде, либо AsyncPipe в шаблоне. Resource API - не замена RxJS вообще, а другой способ доставки данных в шаблон: как сигналы, а не как поток. Выбор между ними зависит от того, в каком мире живёт остальное состояние компонента.
- subscribe / AsyncPipe (Observable) — Данные как поток. Сильны в сложных асинхронных пайплайнах: debounce, switchMap, объединение потоков. AsyncPipe сам управляет подпиской, но состояние loading/error приходится собирать вручную.
- resource / httpResource (сигналы) — Данные как сигналы рядом с остальным сигнальным состоянием. Готовые value/status/error, реактивная перезагрузка по параметрам, естественно для zoneless. Слабее для сложной оркестрации потоков.
Практический ориентир. Если данные напрямую кормят шаблон и компонент уже на сигналах, особенно в zoneless-приложении, resource даёт меньше шаблонного кода и встроенные состояния загрузки. Если нужна сложная композиция асинхронных событий (поиск с debounce, отмена предыдущего запроса, слияние нескольких потоков), сильнее остаётся RxJS с операторами.
Возврат undefined из функции запроса httpResource - штатный способ отложить загрузку. Пока параметр не готов (запись не выбрана, форма не заполнена), запрос не отправляется, ресурс остаётся в состоянии idle. Как только сигнал получит значение, загрузка стартует сама.
Когда resource/httpResource предпочтительнее связки subscribe и AsyncPipe?
Связь с другими темами
Урок сшивает асинхронные данные с сигналами. Опирается на HttpClient и change detection:
- HttpClient — httpResource построен поверх HttpClient и наследует его типизацию
- Change detection и zoneless — Ресурс отдаёт данные как сигналы, и zoneless CD реагирует на них без подписок
Итог
- resource() оборачивает любую асинхронную загрузку (loader) и отдаёт результат как сигналы value(), status(), error()
- httpResource() - специализация поверх HttpClient: принимает URL или объект запроса и наследует типизацию через дженерик
- Реактивные параметры запроса: когда читаемый внутри сигнал меняется, ресурс автоматически перезапрашивает данные
- status() даёт состояние загрузки (idle, loading, resolved, error), а isLoading() - удобный булев сигнал для шаблона
- Resource заменяет связку ручной subscribe и AsyncPipe там, где данные должны жить как сигналы, особенно в zoneless
Связанные уроки
- ng-26-httpclient — httpResource построен поверх HttpClient, поэтому базовые типизированные запросы идут первыми
- ng-11-signals-intro — resource заводит асинхронные данные именно в сигналы, без понимания сигналов его поведение неясно