Выполнение HTTP запросов

Для работы с HTTP-запросами в Angular используется модуль HttpClientModule и сервис HttpClient. Они обеспечивают типизированный, реактивный и расширяемый API поверх стандартного XMLHttpRequest и Fetch.

Подключение выполняется на уровне корневого или функционального модуля:

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

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

HttpClient внедряется через механизм dependency injection и используется внутри сервисов или компонентов. Архитектурно корректным считается вынос всей логики HTTP-взаимодействия в сервисы.

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

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

Основные методы HTTP

HttpClient реализует стандартные HTTP-методы:

  • get<T>()
  • post<T>()
  • put<T>()
  • patch<T>()
  • delete<T>()
  • head<T>()
  • options<T>()

Каждый метод возвращает Observable, что позволяет использовать реактивный подход и легко управлять асинхронностью.

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

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

Тип <User[]> задаёт ожидаемую структуру ответа и используется TypeScript для статической проверки.


Отправка данных на сервер

POST- и PUT-запросы принимают тело запроса вторым аргументом.

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

Angular автоматически сериализует объект в JSON и устанавливает заголовок Content-Type: application/json.

Для PATCH-запросов используется частичное обновление:

updateUser(id: number, data: Partial<User>) {
  return this.http.patch<User>(`/api/users/${id}`, data);
}

Параметры запроса

Query-параметры передаются через HttpParams. Этот объект иммутабелен, каждый вызов set или append возвращает новый экземпляр.

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

getUsers(page: number, LIMIT: number) {
  const params = new HttpParams()
    .set('page', page)
    .set('LIMIT', LIMIT);

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

Использование HttpParams предотвращает ошибки кодирования URL и повышает читаемость.


HTTP-заголовки

Заголовки задаются через HttpHeaders, также иммутабельные.

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

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

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

На практике ручная установка заголовков используется редко, так как для этого применяются интерцепторы.


Работа с Observable

HTTP-запросы в Angular являются «холодными» observable — они выполняются только при подписке.

this.apiService.getUsers().subscribe(users => {
  this.users = users;
});

Часто используется оператор pipe для трансформации данных:

getUserNames() {
  return this.http.get<User[]>('/api/users').pipe(
    map(users => users.map(u => u.name))
  );
}

Для автоматического управления подписками применяются async pipe или операторы take, takeUntil.


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

Ошибки перехватываются через оператор catchError.

import { catchError } from 'rxjs/operators';
import { throwError } from 'rxjs';

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

Объект ошибки содержит:

  • status — HTTP-код
  • message — сообщение
  • error — тело ответа сервера

Глобальная обработка ошибок HTTP обычно выносится в интерцепторы.


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
  }
]

Типичные сценарии использования интерцепторов:

  • добавление токена авторизации
  • логирование
  • глобальная обработка ошибок
  • отображение индикатора загрузки

Типы ответов и наблюдение за событиями

По умолчанию HttpClient возвращает тело ответа. Поведение можно изменить через параметр observe.

this.http.get('/api/data', { observe: 'response' });

Варианты:

  • 'body' — только тело
  • 'response' — полный HttpResponse
  • 'events' — поток событий (загрузка, прогресс)

Отслеживание прогресса загрузки файлов:

this.http.post('/api/upload', file, {
  reportProgress: true,
  observe: 'events'
});

Работа с различными форматами данных

Angular поддерживает разные типы ответов через responseType.

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

Поддерживаемые значения:

  • 'json' (по умолчанию)
  • 'text'
  • 'blob'
  • 'arraybuffer'

Это критично при работе с файлами, бинарными данными и текстовыми API.


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

Отмена выполняется через отписку от observable.

const sub = this.apiService.getUsers().subscribe();

sub.unsubscribe();

В связке с takeUntil часто используется Subject, завершаемый при уничтожении компонента.


Архитектурные принципы

  • HTTP-логика должна находиться в сервисах
  • Компоненты не должны знать детали API
  • Все повторяющиеся операции выносятся в интерцепторы
  • Типизация ответов обязательна
  • Асинхронность обрабатывается реактивно, без Promise.then

Такой подход обеспечивает масштабируемость, тестируемость и предсказуемое поведение приложения при работе с удалёнными API.