Angular - HttpClient, сервисы и файлы окружения

Внимание

Данный материал является частью цикла статей «Frontend приложение на Angular». Не забудьте посмотреть другие статьи по этой теме :-)

  1. Angular - Подготовка проекта для нового приложения
  2. Angular - навигация и маршрутизация
  3. Angular - HttpClient, сервисы и файлы окружения
  4. Angular - Ленивая загрузка данных (lazy loading)
  5. Angular - обработка ошибок
  6. Angular - декораторы и директивы @Input и @Output
  7. Angular - валидация формы и POST запрос
  8. Angular - Работа с запросами PUT
  9. Angular - Работа с DELETE запросами

HttpClientModule и Angular HttpClient

В настоящее время мы используем HttpClientModule, представленный в Angular 4.3, а не старый HttpModule. Новый модуль дает нам некоторые преимущества при обработке ответов и обработке ошибок. Со старым HttpModule нам пришлось бы сопоставить наш ответ и преобразовать его в JSON. Следовательно, нам придется использовать библиотеку RxJS, потому что эта библиотека позволяет использовать функцию карты. В новых HttpClientModule и Angular HttpClient ответ JSON устанавливается по умолчанию. Таким образом, наш проект вообще не требует преобразования результатов.

Один из способов проверить нашу версию angular - запустить приложение и открыть инструменты разработчика. Мы увидим версию в теге <app-root></app-root>:

Работа с файлами среды (Environment Files)

Пока этот проект находится в режиме разработки, адрес сервера - http://localhost: 5000. Адрес сервера в производственной будет другим, например www.accountowner.com. Мы хотим, чтобы об этом позаботился Angular. Таким образом, в режиме разработки он должен отправлять запросы на localhost:5000, а в производственной среде - на другой адрес.

Давайте реализуем это.

На боковой панели кода Visual Studio найдите папку сред. Внутри этой папки вы найдете два файла: environment.prod.ts и environment.ts. Мы собираемся использовать первый для настройки prod-окружения, а второй - для настройки локальной среды разработки.

Пора нам изменить эти файлы.

environment.prod.ts:

export const environment = {
  production: true,
  urlAddress: 'http://www.accountowner.com'
};

environment.ts:

export const environment = {
  production: false,
  urlAddress: 'http://localhost:5000'
};

Теперь мы собираемся создать службу, которая предоставит нам допустимую среду urlAddress.

Давайте создадим новый файл environment-url.service.ts с помощью команды :

ng g service shared/services/environment-url --skipTests

Подробнее о сервисах Angular

Сервисы - это просто классы, которые предоставляют нам некоторую бизнес-логику, относящуюся к нашим компонентам. Эти службы должны быть внедрены в компонент с помощью внедрения конструктора. Кроме того, наш код становится более удобным и читаемым.

Когда мы хотим использовать службу, нам нужно внедрить ее в конструктор компонента. Поэтому его всегда украшает декоратор @Injectable. Используйте службы всякий раз, когда у вас есть код, который вы можете повторно использовать в других компонентах, или извлеките часть кода из своих компонентов:

@Injectable({
  providedIn: 'root',
})

Продолжим работу с файлами среды, изменив файл environment-url.service.ts:

import { environment } from './../../../environments/environment';
import { Injectable } from '@angular/core';

@Injectable({
  providedIn: 'root'
})
export class EnvironmentUrlService {
  public urlAddress: string = environment.urlAddress;
  constructor() { }
}

Свойство urlAddress принимает значение urlAddress, определенного в файле среды. Angular знает, является ли это производственной средой или средой разработки, и предоставит нам действительное значение urlAddress. Вы можете проверить это в файле angular.json:

"configurations": {
            "production": {
              "fileReplacements": [
                {
                  "replace": "src/environments/environment.ts",
                  "with": "src/environments/environment.prod.ts"
                }
              ],

Как видите, Angular заменит файлы в производственном режиме.

Создание файла репозитория Angular

Давайте настроим HttpClientModule и создадим службу репозитория.

Во-первых, нам нужно импортировать HttpClientModule внутри файла app.module.ts:

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

Затем поместим его в массив импорта:

imports: [
    BrowserModule,
    HttpClientModule,
    RouterModule.forRoot([
      { path: 'home', component: HomeComponent },
      { path: '404', component : NotFoundComponent},
      { path: '', redirectTo: '/home', pathMatch: 'full' },
      { path: '**', redirectTo: '/404', pathMatch: 'full'}
    ])
  ]

Теперь давайте создадим служебный файл и назовем его repository.service.ts. Поместите его в ту же папку, в которой находится служба среды. В этом сервисе мы собираемся создавать запросы на получение, публикацию, размещение и удаление:

ng g service shared/services/repository --skipTests

Далее изменим службу репозитория:

import { Injectable } from '@angular/core';
import { HttpClient, HttpHeaders } from '@angular/common/http'; 
import { EnvironmentUrlService } from './environment-url.service';

@Injectable({
  providedIn: 'root'
})
export class RepositoryService {

  constructor(private http: HttpClient, private envUrl: EnvironmentUrlService) { }

  public getData = (route: string) => {
    return this.http.get(this.createCompleteRoute(route, this.envUrl.urlAddress));
  }
 
  public create = (route: string, body) => {
    return this.http.post(this.createCompleteRoute(route, this.envUrl.urlAddress), body, this.generateHeaders());
  }
 
  public update = (route: string, body) => {
    return this.http.put(this.createCompleteRoute(route, this.envUrl.urlAddress), body, this.generateHeaders());
  }
 
  public delete = (route: string) => {
    return this.http.delete(this.createCompleteRoute(route, this.envUrl.urlAddress));
  }
 
  private createCompleteRoute = (route: string, envAddress: string) => {
    return `${envAddress}/${route}`;
  }
 
  private generateHeaders = () => {
    return {
      headers: new HttpHeaders({'Content-Type': 'application/json'})
    }
  }
}

Пояснение к коду RepositoryService

Сначала мы внедряем Angular HttpClient и переменную среды в конструктор. Затем мы создаем функции, которые будут заключать наши запросы. Функция getData является оболочкой для всех запросов GET. Он принимает параметр маршрута в виде строки (api/owner или api/owner/id…), а затем объединяет его с переменной окружения (localhost или www…). После всего этого у нас будет маршрут типа http://localhost:5000/api/owner, если это среда разработки, которая идеально соответствует нашим требованиям на стороне сервера.

Вторая функция, create, является оболочкой для запросов POST. Он также генерирует маршрут, но дополнительно получает тело (объект, который мы создаем) и генерирует заголовки. В этом примере мы просто создаем Content-Type внутри заголовка. Но если нам нужны дополнительные значения внутри заголовка, мы могли бы просто добавить еще одну пару «ключ-значение» внутри объекта HttpHeaders.

Функция update во многом аналогична функции create, за исключением того, что она отправляет запрос PUT.

Наконец, функция delete является оболочкой для запроса DELETE, которая принимает такой маршрут, как (api/owner/id).

Подписка на HTTP-вызовы

Для работы этих функций-оболочек требуется подписка. В этом посте мы создаем только репозиторий с HTTP-вызовами. Но как только мы начнем создавать наши страницы, мы будем использовать подписку.

Сейчас мы просто покажем вам один пример подписки:

public result: any;

constructor(private repo: RepositoryService) { }

public consumeGetFromRepository() {
    this.repo.getData('api/owner/24fd81f8-d58a-4bcc-9f35-dc6cd5641906')
      .subscribe(res => {
        this.result = res;
      },
      (error) => {
        this.handleErrors(error);
      })
  }

Как вы могли заметить, мы вызываем функцию getData из репозитория, но эта функция не будет выполняться, пока мы не вызовем функцию подписки. Вызывая функцию подписки, мы собираемся выполнить функцию getData. Результат ответа будет сохранен в параметре res.

Заключение

Отлично, теперь наш репозиторий подготовлен и мы готовы к созданию компонентов, которые будут использовать функции этого репозитория для отображения результатов в браузере.

Прочитав этот пост, вы узнали:

  • Что такое HttpClientModule
  • Как работать с файлами окружения в Angular
  • Что такое сервисы Angular
  • Как использовать HTTP-запросы
  • Способ подписки на HTTP-запросы

Спасибо, что прочитали этот пост, надеюсь, он был вам полезен.

В следующей статье, я покажу вам, как использовать отложенную загрузку контента в Angular. Более того, мы собираемся отображать данные результатов на странице.