От автора: в Angular 4.3 представлен новый модуль HttpClientModule. Он доступен в пакете @angular/common/http и повторно реализует старый HttpModule. В HttpClientModule включен новый сервис HttpClient. С его помощью можно посылать HTTP-запросы и обрабатывать ответы внутри приложения. Давайте рассмотрим, как использовать в этой версии Angular HttpClient.
Создание нового проекта Angular 4.3
Сначала необходимо создать новый проект Angular 4.3. Легче всего это сделать через Angular CLI (командную строку Angular). Если у вас еще не установлен Angular CLI, сначала выполните следующую команду для установки последней версии:
1 |
$ npm install -g @angular/cli@latest |
Создастся новая папка nghttp01, в которую загрузится шаблон проекта и автоматически установятся зависимости. Затем откройте package.json в любимом редакторе и посмотрите, чтобы все зависимости Angular содержали версию < 4.3.0. После обновления package.json необходимо выполнить следующую команду
1 |
$ npm install |
в папке проекта, чтобы обновить соответствующие пакеты.
Делаем HttpClient доступным в проекте
Чтобы использовать HttpClient внутри компонентов, сначала необходимо подключить HttpClientModule в приложение Angular. Первым делом необходимо импортировать модуль HttpClient в корневой модуль приложения в файл app.module.ts:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
import { BrowserModule } from '@angular/platform-browser'; import { NgModule } from '@angular/core'; import { HttpClientModule } from '@angular/common/http'; import { AppComponent } from './app.component'; @NgModule({ declarations: [ AppComponent ], imports: [ BrowserModule, HttpClientModule ], providers: [], bootstrap: [AppComponent] }) export class AppModule { } |
После импорта HttpClient можно использовать в компонентах. Чтобы HttpClient стал доступен в классе компонента, необходимо вставить его в конструктор класса, как показано ниже:
1 2 3 4 5 6 7 8 9 10 11 12 |
import { Component, OnInit } from '@angular/core'; import { HttpClient } from '@angular/common/http'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class AppComponent { title = 'app'; constructor(private http: HttpClient){ } } |
HttpClient будет использовать браузерный API XMLHttpRequest для выполнения HTTP-запросов. Выполнить HTTP-запрос определенного типа можно с помощью методов, отвечающих HTTP-глаголам: get, post, put, delete, patch, head, jsonp.
Запрос данных через HttpClient
Давайте напишем простой пример, который с помощью REST API с GitHub запрашивает данные пользователя. Вставьте следующий код в app.component.ts:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
import { Component, OnInit } from '@angular/core'; import { HttpClient } from '@angular/common/http'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class AppComponent implements OnInit { title = 'app'; results = ''; constructor(private http: HttpClient){ } ngOnInit(): void { this.http.get('//api.github.com/users/seeschweiler').subscribe(data => { console.log(data); }); } } |
В консоли браузера должно отобразиться примерно следующее:
Результат показывает, что в JSON ответ можно обращаться напрямую с помощью подписки на Observable, который возвращается из метода get.
Типизированный ответ
Из консоли браузера видно, что у возвращенного JSON объекта много свойств. Если попробовать получить доступ к одному из них с помощью точки, вы получите ошибку:
1 |
console.log(data.login); |
Ошибка гласит «свойство login не существует на типе Object. Данные имеют тип Object, поэтому к свойствам нельзя обращаться напрямую. Однако мы можем отнести ответ Object к типу, содержащему соответствующие свойства. Давайте определим тип интерфейса, который содержит свойства из ответа:
1 2 3 4 5 |
interface UserResponse { login: string; bio: string; company: string; } |
Теперь с помощью UserResponse давайте отнесем возвращаемый тип вызова get:
1 2 3 4 5 |
this.http.get<UserResponse>('//api.github.com/users/seeschweiler').subscribe(data => { console.log("User Login: " + data.login); console.log("Bio: " + data.bio); console.log("Company: " + data.company); }); |
Теперь данные можно получить через data.login, data.bio и data.company. В консоли браузера теперь должен быть результат:
Обработка ошибок
HTTP-запрос может завершиться неудачей. На его отправку может повлиять слабое соединение или другие факторы, которые нельзя предсказать. Поэтому всегда необходимо писать обработчики ошибок. Для этого можно добавить второй колбек-метод к методу subscribe:
1 2 3 4 5 6 7 8 9 10 |
this.http.get<UserResponse>('//api.github.com/users/seeschweiler').subscribe( data => { console.log("User Login: " + data.login); console.log("Bio: " + data.bio); console.log("Company: " + data.company); }, err => { console.log("Error occured.") } ); |
По ошибке можно получить более определенную информацию, если указать параметр типа HttpErrorResponse для функции-обработчика ошибок. HttpErrorResponse необходимо импортировать из @angular/common/http:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
this.http.get<UserResponse>('//api.github.com/users/seeschweiler').subscribe( data => { console.log("User Login: " + data.login); console.log("Bio: " + data.bio); console.log("Company: " + data.company); }, (err: HttpErrorResponse) => { if (err.error instanceof Error) { console.log("Client-side error occured."); } else { console.log("Server-side error occured."); } } ); |
Отправка данных через HttpClient
Теперь давайте посмотрим, как отправлять данные через HttpClient. Для этого мы будем использовать метод post объекта HttpClient. Конечно, нам нужен backend, предлагающий REST API, который принимает POST HTTP запросы. Чтобы не ставить свой backend API, мы можем использовать JSONPlaceholder – ложный онлайн REST API для тестирования и прототипирования.
(//jsonplaceholder.typicode.com/)
Endpoint //jsonplaceholder.typicode.com/posts поддерживает POST HTTP-запросы. Давайте с помощью endpoint создадим новую post запись:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
const req = this.http.post('//jsonplaceholder.typicode.com/posts', { title: 'foo', body: 'bar', userId: 1 }) .subscribe( res => { console.log(res); }, err => { console.log("Error occured"); } ); |
Здесь видно, что данные post запроса передаются в метод post в качестве второго параметра в формате JSON. Возвращаем ответ, чтобы проверить, создался ли объект:
Перехватчики
Одна из новых функций нового модуля HttpClient – доступность перехватчиков. Перехватчики находятся между вашим приложением и backend. С помощью перехватчиков можно трансформировать запрос от приложения до его принятия на backend. То же самое касается ответов. Если с backend прилетает ответ, перехватчик может его трансформировать перед получением его в приложении.
Лучше всего понять перехватчики можно на простом примере. Создайте новый файл githubauth.interceptor.ts и вставьте в него следующий код:
1 2 3 4 5 6 7 8 9 |
import { Injectable } from '@angular/core'; import { HttpEvent, HttpInterceptor, HttpHandler, HttpRequest } from '@angular/common/http'; import { Observable } from 'rxjs/observable'; @Injectable() export class GithubAuthInterceptor implements HttpInterceptor { intercept (req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> { return next.handle(req); } } |
Класс перехватчика GithubAuthInterceptor реализует интерфейс HttpInterceptor, который входит в библиотеку @angular/common/http. Реализация интерфейса обязует нам добавить метод intercept в класс. Этот метод выполняет основную работу перехватчика. В метод передается два параметра. Первый – сам запрос. Второй – следующий обработчик HTTP, в который необходимо передать запрос для дальнейшей обработки.
В первом примере метод intercept просто передает запрос в следующий обработчик. Поняв подход перехватчика, мы можем перейти к манипулированию запросом в методе intercept:
1 2 3 4 5 6 7 8 9 10 11 12 |
import { Injectable } from '@angular/core'; import { HttpEvent, HttpInterceptor, HttpHandler, HttpRequest } from '@angular/common/http'; import { Observable } from 'rxjs/observable'; @Injectable() export class GithubAuthInterceptor implements HttpInterceptor { intercept (req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> { const authReq = req.clone({ headers: req.headers.set('Authorization', 'token <your GitHub token>') }); return next.handle(authReq); } } |
Сначала мы создаем новый запрос с помощью метода clone. В то же время мы передаем JSON объект со свойствами заголовков. Для создания заголовка используем метод req.headers.set для свойства Authorization. С помощью этого свойства отправляется токен доступа GitHub.
Вновь созданный объект запроса (с заголовком) передается для дальнейшей обработки с помощью метода next.handle.
Подача перехватчика
Чтобы активировать перехватчик в приложении, его необходимо предоставить главному модулю приложения AppModule в файле app.module.ts:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
import { BrowserModule } from '@angular/platform-browser'; import { NgModule } from '@angular/core'; import { HttpClientModule } from '@angular/common/http'; import { HTTP_INTERCEPTORS } from '@angular/common/http'; import { AppComponent } from './app.component'; import { GithubAuthInterceptor } from './githubauth.interceptor'; @NgModule({ declarations: [ AppComponent ], imports: [ BrowserModule, HttpClientModule ], providers: [{ provide: HTTP_INTERCEPTORS, useClass: GithubAuthInterceptor, multi: true }], bootstrap: [AppComponent] }) export class AppModule { } |
Сперва мы импортируем GithubAuthInterceptor, после чего вставляем новый объект в массив, который назначается свойству провайдера @NgModule. Этот объект содержит три свойства:
provide – для передачи HTTP перехватчика необходимо установить в HTTP_INTERCEPTORS
useClass – необходимо задать значение типа нашего класса перехватчика
multi – необходимо задать в multi, чтобы сказать Angular, что HTTP_INTERCEPTORS – массив значений, а не одно значение
Перехватчик активен, заголовок Authorization добавлен во все запросы и посылается автоматически.
Автор: Sebastian Eschweiler
Источник: //medium.com/
Редакция: Команда webformyself.