HttpClient сервис

HttpClient — встроенный сервис Angular для выполнения HTTP-запросов к серверным API. Он построен поверх XMLHttpRequest и fetch, интегрирован с RxJS и системой внедрения зависимостей, поддерживает строгую типизацию, интерсепторы, автоматическую сериализацию JSON и централизованную обработку ошибок. Использование HttpClient формирует чистый слой доступа к данным и отделяет сетевую логику от компонентов.


Подключение HttpClient

Сервис доступен после импорта модуля HttpClientModule.

import { HttpClientModule } FROM '@angular/common/http';

@NgModule({
  imports: [HttpClientModule]
})
export class AppModule {}

В Angular с standalone-компонентами применяется провайдер:

import { provideHttpClient } from '@angular/common/http';

bootstrapApplication(AppComponent, {
  providers: [provideHttpClient()]
});

Базовое использование и типизация

HttpClient возвращает Observable<T>, где T — ожидаемый тип ответа. Типизация повышает надежность и упрощает работу с данными.

@Injectable({ providedIn: 'root' })
export class UsersService {
  constructor(private http: HttpClient) {}

  getUsers() {
    return this.http.get<User[]>('/api/users');
  }
}

Ключевые особенности:

  • Автоматический парсинг JSON.
  • Строгая типизация ответов.
  • Ленивая модель выполнения запросов (Observable выполняется при подписке).

HTTP-методы

Поддерживаются все стандартные методы:

get<T>(url, options?)
post<T>(url, body, options?)
put<T>(url, body, options?)
patch<T>(url, body, options?)
delete<T>(url, options?)
head<T>(url, options?)
options<T>(url, options?)

Пример POST-запроса:

createUser(user: User) {
  return this.http.post<User>('/api/users', user);
}

Параметры запроса (HttpParams)

Параметры формируются неизменяемым объектом HttpParams.

const params = new HttpParams()
  .set('page', 1)
  .set('LIMIT', 20);

this.http.get<User[]>('/api/users', { params });

Для динамических наборов:

const params = new HttpParams({ fromObject: filters });

Заголовки (HttpHeaders)

Заголовки также неизменяемы.

const headers = new HttpHeaders({
  Authorization: 'Bearer token',
  'X-Custom-Header': 'value'
});

this.http.get('/api/profile', { headers });

Опции запроса

HttpClient поддерживает расширенные опции:

  • observe: 'body' | 'response' | 'events'
  • responseType: 'json' | 'text' | 'blob' | 'arraybuffer'
  • withCredentials
  • reportProgress

Пример получения полного ответа:

this.http.get<User>('/api/profile', {
  observe: 'response'
}).subscribe(response => {
  console.log(response.status);
  console.log(response.headers);
  console.log(response.body);
});

Работа с событиями и прогрессом

Для отслеживания прогресса загрузки:

this.http.post('/api/upload', file, {
  reportProgress: true,
  observe: 'events'
}).subscribe(event => {
  if (event.type === HttpEventType.UploadProgress) {
    const percent = Math.round(100 * event.loaded / (event.total ?? 1));
  }
});

Обработка ошибок

Ошибки представлены объектом HttpErrorResponse.

this.http.get('/api/data').pipe(
  catchError((error: HttpErrorResponse) => {
    if (error.status === 0) {
      // ошибка сети
    } else {
      // серверная ошибка
    }
    return throwError(() => error);
  })
);

Рекомендуется выносить обработку в отдельный слой или интерсептор.


Интерсепторы HTTP

Интерсепторы позволяют перехватывать запросы и ответы глобально.

@Injectable()
export class AuthInterceptor implements HttpInterceptor {
  intercept(req: HttpRequest<any>, next: HttpHandler) {
    const authReq = req.clone({
      setHeaders: {
        Authorization: 'Bearer token'
      }
    });
    return next.handle(authReq);
  }
}

Регистрация:

providers: [
  { provide: HTTP_INTERCEPTORS, useClass: AuthInterceptor, multi: true }
]

Возможности интерсепторов:

  • Добавление токенов авторизации
  • Логирование
  • Централизованная обработка ошибок
  • Кэширование запросов

Отмена запросов

Отмена достигается через отписку от Observable.

const sub = this.http.get('/api/data').subscribe();

// отмена
sub.unsubscribe();

В связке с takeUntil:

this.http.get('/api/data')
  .pipe(takeUntil(this.destroy$))
  .subscribe();

Повторные запросы и ретраи

RxJS-операторы позволяют реализовать повторные попытки.

this.http.get('/api/data').pipe(
  retry(3),
  delay(1000)
);

Для гибкой логики:

retryWhen(errors =>
  errors.pipe(
    scan((count) => count + 1, 0),
    takeWhile(count => count < 3)
  )
);

Загрузка файлов

Для отправки FormData:

const formData = new FormData();
formData.append('file', file);

this.http.post('/api/upload', formData);

Для скачивания бинарных данных:

this.http.get('/api/report', {
  responseType: 'blob'
});

Тестирование HttpClient

Angular предоставляет HttpClientTestingModule и HttpTestingController.

TestBed.configureTestingModule({
  imports: [HttpClientTestingModule]
});

const httpMock = TestBed.inject(HttpTestingController);

service.getUsers().subscribe(users => {
  expect(users.length).toBe(2);
});

const req = httpMock.expectOne('/api/users');
req.flush([{ id: 1 }, { id: 2 }]);

Преимущества:

  • Отсутствие реальных HTTP-запросов
  • Контроль над ответами
  • Проверка корректности URL и методов

Архитектурные рекомендации

  • Сетевую логику размещать в сервисах.
  • Компоненты не должны напрямую работать с HttpClient.
  • Использовать строгую типизацию DTO.
  • Интерсепторы применять для сквозных задач.
  • Не подписываться внутри сервисов, возвращать Observable.

Итоговая роль HttpClient в приложении

HttpClient формирует основу взаимодействия Angular-приложения с внешними API, объединяя реактивный подход, типобезопасность и расширяемость. Его правильное использование обеспечивает масштабируемость, тестируемость и чистоту архитектуры клиентского кода.