Пример 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

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

Как добавить ng-bootstrap компоненты в проект Angular-CLI?

Покажу на примере нового проекта.

ng new project_name
cd project_name
npm install --save bootstrap@next
npm install --save @ng-bootstrap/ng-bootstrap

В angular-cli.json в секцию style надо добавить наш CSS, чтобы глобально подключить стили.

  "styles": [
    "styles.css",
    "../node_modules/bootstrap/dist/css/bootstrap.min.css"
  ],

Отладка Angular в VS Code

Настройка Visual Studio Code используя расширение Debugger for Chrome для отладки Angular приложений

Angular. Can't set breakpoints in VS Code

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