Самый распространенный способ получить данные из web служб — это через Http. И в этой статье мы посмотрим как это можно сделать Http-запрос в Angular 4.3 через новый HttpClient.
Начиная с версии Angular 4.3 появился новый HttpClient. В этой статье описывается только новый клиент.
Angular > 4.3
HttpClientModule
HttpClient
Angular <= 4.3
HttpModule
Http
Замечание: Старая реализация http все еще существует в 4.3, поэтому убедитесь, что вы используете правильный.
Импорт модуля
Прежде всего, нам нужно импортировать HttpClientModule в родительский модуль. Если у вас новый Angular проект, то это скорее всего будет AppModule. Чтобы импортировать модуль, просто добавьте его в раздел imports родительского модуля.
src/app/app.module.ts
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { AppComponent } from './app.component';
// Убедитесь, что вы используете именно этот импорт, чтобы использовать новую версию модуля
import { HttpClientModule } from '@angular/common/http';
@NgModule({
declarations: [
AppComponent,
],
imports: [
BrowserModule,
HttpClientModule // Импортируем модуль
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
Создаем простой сервис
Правильным подходом при построении Angular приложении считается вынос всех HTTP-запросов из компонентов в сервисы, чтобы сделать их полностью независимыми, а все запросы завернуть в отдельные сервисы. Потом например, при тестировании можно будет сделать mocke версию сервиса. Да и код при таком подходе получается более аккуратным.
Обычно для служб заводят отдельную папку в модуле, где же у вас будет сервис, полностью ваш выбор.
У каждой службы есть определенная цель. Например, если мы хотим запросить фотографии кошек через http, то наша служба будет называться CatPictureService. Основа сервиса будет выглядеть примерно так:
src/app/services/catPicture.service.ts
import { Injectable } from '@angular/core';
@Injectable()
export class CatPictureService {
constructor() { }
}
Чтобы сделать http-запрос из нашего сервиса, нам нужен Angular HttpClient. Мы можем его легко добавить посредством инъекции зависимостей (dependency injection, DI).
src/app/services/catPicture.service.ts
import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';
@Injectable()
export class CatPictureService {
constructor(private httpClient: HttpClient) { }
}
Создание запроса
Чтобы сделать запрос, мы добавим новый метод в наш сервис. Методы обычно называются глаголом. На данный момент мы назовем метод «get». Он получит по URL-адресу фотографию кота.
public get(url: string): Observable<any>{
return this.httpClient.get(url);
}
Как вы можете видеть, Angular HttpClient довольно прост. Все, что нам нужно сделать, это вызвать метода get и передать ему url. Данный метод get возвращает объект Observable. Этот класс является частью библиотеки rxjs, которая используется во многих местах Angular'а. Одним из примеров использования является HttpClient.
Подобно обещанию(Promise), наблюдатель(Observable) не содержит в себе сразу значения. Вместо этого у него есть метод подписки(subscribe), где мы можем зарегистрировать обратный вызов(callback). Этот callback вызывается, как только результат будет доступен. Помимо обещания, Observable может вернуть более одного значения. Вы можете вернуть себе поток результатов. Но это не имеет значения для этого урока. В нашем случае Observable возвращает только одно значение.
Подписка на наблюдатели (Subscribing to Observables)
Итак, как мы можем подписаться на наблюдателя, которого вернул наш новый метод, чтобы получить фактическое значение? Это довольно легко. Мы просто вызываем метод подписки subscribe и регистрируем один (или два) метода для обратного вызова. Первый обратный вызов вызывается, когда результат доступен. Он получает результат как параметр. Второй обратный вызов запускается, когда с запросом возникает какая-либо ошибка. В качестве параметра он получает объект ошибки.
Вот как это выглядит в коде. Я составил экземпляр picService. Вам необходимо запровайдить и запросить этот сервис самостоятельно.
this.picService.get('http://anyurl.com').subscibe(value =>{
// value - результат
},
error => {
// error - объект ошибки
});
ПРИМЕЧАНИЕ. Вам всегда нужно подписываться(вызывать метод subscibe) в противном случае запрос не будет сделан!
Опции
Http поддерживает огромный выбор различных параметров, заголовков и форматов. Чтобы сделать все эти разные запросы от HttpClient, все его методы берут в качестве необязательного параметра объект options.
Форматы ответов
Начиная с Angular 4.3, формат ответа по умолчанию — JSON. Это делает использование HttpClient очень простым. Вам больше не нужно анализировать ответ вручную. Angular делает это для вас.
Хотя JSON является наиболее распространенным форматом ответов, есть много примеров, когда вы не можете использовать JSON. Например, при запросе фотографий кошечек.
Чтобы избежать автоматического анализа ответа, мы можем определить заранее свойство responseType через объекта options.
{ responseType: 'text' }
Заголовки
Чтобы добавить заголовки в запрос, мы используем свойство headers объекта options. Для этого нам нужен объект HttpHeaders. Он содержит все наши определения заголовков. Не используйте объект Headers, так как он является частью старого клиента Http.
const headers = new HttpHeaders({ 'Content-Type': 'application/json' });
const options = { headers: headers };
URL параметры
Мы также можем определить параметры url внутри объекта options. Для этого нам нужно создать объект HttpParams. Таким образом, нам не нужно добавлять их в строку url.
const params = new HttpParams().set('id', '3');
const options = {params: params};
Отслеживание прогресса
Одной из новых особенностей нового HttpClient является возможность отслеживание хода выполнения запроса. Например, если вы хотите загрузить большой файл, вы, вероятно, хотите сообщить о ходе загрузки пользователю.
Для этого нам нужно разбить наш запрос в отдельном объекте запроса. Чтобы получить прогресс, нам нужно установить для свойства reportProgress значение true.
import { Observable } from 'rxjs/Observable';
import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { HttpRequest } from "@angular/common/http";
import { Subject } from "rxjs/Subject";
import { HttpEventType } from "@angular/common/http";
import { HttpResponse } from "@angular/common/http";
public post(url: string, file: File): Observable<number>{
var subject = new Subject<number>()
const req = new HttpRequest('POST', url, file, {
reportProgress: true,
});
this.httpClient.request(req).subscribe(event => {
if (event.type === HttpEventType.UploadProgress) {
const percentDone = Math.round(100 * event.loaded / event.total);
subject.next(percentDone);
} else if (event instanceof HttpResponse) {
subject.complete();
}
});
return subject.asObservable();
}
Метод post возвращает объект наблюдателя(Observable), представляющий ход загрузки.
Перехватчики (Interceptors)
Еще одной замечательной особенностью нового HttpClient являются перехватчики. В некоторых случаях вам может потребоваться изменить запрос до того, как он попадет на сервер. Или вы хотите изменить каждый ответ. Вы можете сделать это с помощью Interceptor. Это своего рода промежуточное ПО между http-api и фактическим запросом.
Одним из распространенных вариантов использования может быть аутентификация. Чтобы получить ответ с сервера, вам часто нужно добавить какой-то механизм проверки подлинности в запрос. Конечно, вы можете просто изменить заголовок авторизации в своей службе. Но эта задача всегда одна и та же, не так ли? Это всегда один и тот же протокол. Он никогда не меняется, даже между приложением. Так почему бы нам не написать логику один раз и повторно использовать ее повсюду?
Определение перехватчика
Подобно сервису, перехватчик является инъекционным(Injectable).
import { Observable } from 'rxjs/Observable';
import {Injectable} from '@angular/core';
import {HttpEvent, HttpInterceptor, HttpHandler, HttpRequest} from '@angular/common/http';
@Injectable()
export class AuthenticationInterceptor implements HttpInterceptor {
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
req.headers.append('Authorization', '<SOME-TOKEN>')
return next.handle(req);
}
}
Поскольку приложение может иметь несколько перехватчиков, они организованы в цепочку. Первый элемент вызывается Angular'ом. Впоследствии мы несем ответственность за передачу запроса следующему перехватчику. Чтобы это сделать, мы вызываем метод handle следующего элемента в цепочке, как только мы закончим.
Прежде чем мы это сделаем, мы можем изменить запрос, как нам нравится. Например, добавьте токен в заголовок авторизации.
Этот пример отнюдь не является полным или многоразовым. Но это должно дать вам представление о том, как можно отсюда продолжить.
Представление перехватчиков
Так же, как сервисы, мы также должны запровайдить перехватчики. Для этого ваш родительский модуль (AppModule) должен выглядеть примерно так:
src/app/app.module.ts
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { AppComponent } from './app.component';
// Убедитесь, что вы используете именно этот импорт, чтобы использовать новую версию модуля
import { HttpClientModule } from '@angular/common/http';
import { HTTP_INTERCEPTORS } from '@angular/common/http';
@NgModule({
declarations: [
AppComponent,
],
imports: [
BrowserModule,
HttpClientModule // импорт модуля
],
providers: [{
provide: HTTP_INTERCEPTORS,
useClass: AuthenticationInterceptor,
multi: true,
}],
bootstrap: [AppComponent]
})
export class AppModule { }
Итого
Теперь мы знаем, как можем отправлять или получать внешние данные через http. Мы также узнали, какие варианты мы можем использовать и как отслеживать прогресс.
Надеюсь, вам понравилась эта статья.
Автор: Hooter