Пример Angular Interceptors

Главной особенностью @angular/common/http является interceptors, возможность объявлять перехватчики, которые находятся между вашим приложением и бэкэндом. Когда ваше приложение делает запрос, перехватчики преобразуют его перед отправкой на сервер (Удобно добавлять заголовки к запросом). Применяется для всего: от аутентификации до логирования.

Создание приложения

ng new interceptors
cd interceptors
ng g service api

Создадим сервис api.service.ts, который будет получать данные с jsonplaceholder.typicode.com

import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs/Observable';

export interface Posts {
  userId: number;
  id: number;
  title: string;
  body: string;
}

@Injectable()
export class ApiService {

  private postsURL = 'https://jsonplaceholder.typicode.com/posts';

  constructor(private http: HttpClient) { }

  getData(): Observable<Posts> {

    return this.http
      .get<Posts>(this.postsURL);
  }

}

В главный модуль app.module.ts добавляем

import { HttpClientModule, HTTP_INTERCEPTORS } from '@angular/common/http'; // <- добавлено

...
  imports: [
    BrowserModule,
    HttpClientModule // <- добавлено
  ],
...

HTML код app компонента

<div style="text-align:center">
  <h1>
    Welcome to {{title}}!
  </h1>
  <img width="300" src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNTAgMjUwIj4KICAgIDxwYXRoIGZpbGw9IiNERDAwMzEiIGQ9Ik0xMjUgMzBMMzEuOSA2My4ybDE0LjIgMTIzLjFMMTI1IDIzMGw3OC45LTQzLjcgMTQuMi0xMjMuMXoiIC8+CiAgICA8cGF0aCBmaWxsPSIjQzMwMDJGIiBkPSJNMTI1IDMwdjIyLjItLjFWMjMwbDc4LjktNDMuNyAxNC4yLTEyMy4xTDEyNSAzMHoiIC8+CiAgICA8cGF0aCAgZmlsbD0iI0ZGRkZGRiIgZD0iTTEyNSA1Mi4xTDY2LjggMTgyLjZoMjEuN2wxMS43LTI5LjJoNDkuNGwxMS43IDI5LjJIMTgzTDEyNSA1Mi4xem0xNyA4My4zaC0zNGwxNy00MC45IDE3IDQwLjl6IiAvPgogIDwvc3ZnPg==">
</div>
<div class="container">
  <div class="row">
      <table class="table">
          <thead class="thead-inverse">
            <tr>
                <th class="text-center">ID</th>
                <th class="text-center">Title</th>
                <th class="text-center">Body</th>
            </tr>
          </thead>
          <tbody>
            <tr *ngFor="let post of posts">
                <td>{{post.id}}</td>
                <td class="text-center">{{post.title}}</td>
                <td>{{post.body}}</td>
            </tr>
          </tbody>
      </table>
  </div>
</div>

Написание перехватчика

Чтобы реализовать перехватчик, нужно создать класс, реализующий интерфейс HttpInterceptor, который имеет один метод intercept(). Он принимает два параметра (req, next) и возварщает Observable. По сути первый параметр входящий запрос, второй - исходящий. Поэтому нам необходимо вернуть запрос, делается через метод handle. Далее следует зарегистрировать класс перехватчика в приложении.

ng g class api.interceptor

Для начала создадим простой перехватчик, который ничего не делает, просто принимает и отправляет запрос, не изменяя его:

import { Injectable } from '@angular/core';
import { Observable } from 'rxjs/Observable';
import { HttpEvent, HttpInterceptor, HttpHandler, HttpRequest } from '@angular/common/http';

@Injectable()
export class ParamInterceptor implements HttpInterceptor {
    intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
        return next.handle(req);
    }
}

Теперь нужно зарегистрировать перехватчик. Сделаем это в app.module.ts.

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { HttpClientModule, HTTP_INTERCEPTORS } from '@angular/common/http'; // <- добавлено

import { AppComponent } from './app.component';
import { ApiService } from './api.service';
import { AuthInterceptor, ParamInterceptor } from './api.interceptor';

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    HttpClientModule // <- добавлено
  ],
  providers: [
    ApiService, {
    provide: HTTP_INTERCEPTORS,
    useClass: ParamInterceptor,
    multi: true
  }],
  bootstrap: [AppComponent]
})
export class AppModule { }

Теперь все запросы в приложении обрабатываются перехватчиком ParamInterceptor. Добавим логики. Будем добавлять параметр UserId = 7, для запросов к серверу jsonplaceholder.typicode.com.

import { Injectable } from '@angular/core';
import { Observable } from 'rxjs/Observable';
import { HttpEvent, HttpInterceptor, HttpHandler, HttpRequest } from '@angular/common/http';

@Injectable()
export class ParamInterceptor implements HttpInterceptor {
    intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {

    if (req.url.includes('jsonplaceholder.typicode.com')) {
        const paramReq = req.clone({
            params: req.params.set(
                'userId',
                '7'
            )
        });
        return next.handle(paramReq);
    } else {
        return next.handle(req);
    }

    }
}

Функция clone используется, потому что объект req является immutable (Неизменяемым).

Результат

Посмотреть на GitHub, Stackblitz

Похожие записи

Angular. Can't set breakpoints in VS Code

Вариант решения проблемы, когда не срабатывают точки остановки при разработке Angular приложений в редакторе VS Code
10 апреля 2018 г. в Angular

Переиспользуемые анимации в Angular

Для создания анимации используется функция animation(). Для её использования — useAnimation(). Приводится пример переиспользуемой анимации, а также создание анимации через литерал объекта.

09 октября 2018 г. в Angular

Angular. Редирект по условию

Пример условного перенаправления пользователя в зависимости от некого количества

  • 0 - dashboard
  • 1 - карточка
  • 2 и более - список
09 января 2019 г. в Angular

Вставить <script> в Angular компонент

Добавление сторонних скриптов в Angular по запросу. Как известно, добавить скрипт через шаблон невозможно. Представлено решение как это сделать программно.

15 ноября 2019 г. в Angular

Вложенные формы Angular

Рассматриваются варианты встраивания форм, позволяющие переиспользовать набор полей вводе со своей логикой. @Input() родительской формы, @Output() дочерней формы, ViewChild(), ControlValueAccessor, ControlContainer