HttpClient: общение с сервером
HttpClient — официальный способ Angular ходить в сеть: типизированные запросы, удобные методы и интеграция с реактивностью.
«Приложение без данных — красивая пустышка. HttpClient — это мост между вашим интерфейсом и реальным миром на сервере».
Реальные приложения берут данные с сервера. Angular даёт для этого HttpClient — обёртку над сетевыми запросами с типизацией и реактивностью. Сначала его нужно подключить при старте приложения, желательно с современным движком withFetch():
// main.ts
import { provideHttpClient, withFetch } from '@angular/common/http';
bootstrapApplication(AppComponent, {
providers: [
provideHttpClient(withFetch()),
],
});
Дальше внедряем HttpClient в сервис и делаем запросы. Они возвращают Observable — поток, на который нужно подписаться, чтобы запрос реально ушёл:
import { Injectable, inject } from '@angular/core';
import { HttpClient } from '@angular/common/http';
interface Product { id: number; title: string; price: number; }
@Injectable({ providedIn: 'root' })
export class ProductApi {
private http = inject(HttpClient);
private base = 'https://api.shop.ru';
getAll() {
return this.http.get<Product[]>(`${this.base}/products`);
}
create(p: Partial<Product>) {
return this.http.post<Product>(`${this.base}/products`, p);
}
}
Обобщённый параметр <Product[]> подсказывает TypeScript форму ответа — дальше вы работаете с типизированными данными. Удобный способ влить ответ в реактивность — превратить Observable в сигнал через toSignal().
Как работает под капотом
Метод http.get() не отправляет запрос сразу — он лишь описывает его и возвращает Observable. Запрос уходит в сеть только при подписке (вручную или через async-pipe / toSignal). withFetch() переключает движок на нативный браузерный fetch, что лучше для серверного рендеринга и современных сценариев.
http.get<Product[]>(url)
|
возвращает Observable (запрос ещё НЕ ушёл)
|
подписка (subscribe / async / toSignal)
|
запрос уходит в сеть -> ответ -> данные в компонент
Частые ошибки
- Забыть
provideHttpClient()— внедрениеHttpClientупадёт с ошибкой «нет провайдера». - Ждать, что запрос уйдёт без подписки. Observable «холодный»: нет подписки — нет запроса.
- Делать HTTP прямо в компоненте. Запросы — работа сервиса, компонент только отображает.
Best practices
- Подключайте
provideHttpClient(withFetch())в современных приложениях. - Инкапсулируйте все запросы в сервисах-«репозиториях» (
ProductApi), а не в компонентах. - Типизируйте ответы через обобщения
get<T>— это ловит ошибки на этапе компиляции.
Итоги. HttpClient с provideHttpClient(withFetch()) делает типизированные запросы, возвращая Observable, который оживает при подписке. Запросы держим в сервисах. Дальше — как обрабатывать ответы и ошибки реактивно.
Закрепляем
HttpClient — официальный мост между вашим интерфейсом и сервером. Подключается он один раз при старте через provideHttpClient(), желательно с современным движком withFetch(), после чего его можно внедрять в любой сервис. Методы get, post, put, delete покрывают основные операции, а обобщённый параметр вроде get<Product[]> подсказывает TypeScript форму ответа, давая типобезопасность на всём пути данных.
Самая важная и неочевидная деталь: запрос не уходит в сеть в момент вызова get(). Метод лишь возвращает «холодный» Observable — описание запроса, которое оживает только при подписке. Подписаться можно вручную через subscribe, в шаблоне через async-pipe или, что чаще всего удобнее, превратив поток в сигнал через toSignal(). И ещё одно архитектурное правило: держите все запросы в сервисах-репозиториях, а не в компонентах. Компонент должен отображать данные, а не знать, по какому URL и как они добываются.
| Элемент | Назначение |
|---|---|
| provideHttpClient(withFetch()) | Подключить HTTP |
| http.get<T>(url) | Типизированный запрос |
| Observable | Холодный поток (нужна подписка) |
| toSignal() | Поток в сигнал |