Резолвер в Angular для предвыборки данных

Что такое резолвер в Angular?

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

В некоторых сценариях может потребоваться предварительно загрузить данные для отображения компонента. В противном случае пришлось бы сначала отображать пустой компонент и затем отправлять запросы к API на получение данных.

Для чего в маршрутизации на Angular используются резолверы?

Резолверы на Angular обычно используются, чтобы предоставить асинхронные данные загружаемому маршруту. И эти асинхронные данные должны быть отображены в компоненте.

Есть два подхода для отображения компонента с использованием асинхронных данных:

  1. Загрузка данных после загрузки компонента. Сначала компонент отображается без каких-либо данных. После чего выполняется Ajax-запрос для получения данных компонента. Затем компонент повторно визуализируется для отображения данных, ставших доступными после Ajax-запроса. Это всё равно что сначала отображать пустой шаблон, а затем добавлять к нему данные. Данные могут быть доступны после небольшой задержки с момента первого отображения компонента.
  2. Загрузка данных перед загрузкой компонента. Данные должны быть под рукой, прежде чем отображать компонент. Если данные необходимо извлечь из асинхронного вызова, компонент сначала будет ждать, когда они станут доступны, прежде чем визуализировать компонент в первый раз. Поэтому пустой шаблон отображать никогда не придётся. Маршрут ждёт, когда данные станут доступны для первого отображения компонента.

Как создать сервис резолверов на Angular?

Чтобы реализовать сервис резолверов, потребуется:

  1. Импортировать интерфейс «Resolve» из «@angular/router».
  2. Создать класс сервиса, реализующий этот интерфейс «Resolve».
  3. Переопределить функцию «resolve()», указав HTTP-запрос, который нужно ждать. Эта функция может вернуть Promise или Observable.
  4. Добавить этот класс сервиса в корневой модуль «root».
  5. Добавить в компонент «ActivatedRouteSnapshot», который загружается для использования данных, доступных из AJAX-запроса, указанного в функции «resolve».

Реализуем сервис резолверов

Создадим «DataService», чтобы извлечь данные для «EmployeeListComponment». Этот сервис будет извлекать список Employee (сотрудников) компании из простого вызова API.

Начнём с реализации сервиса, который будет резолвить данные, необходимые компоненту перед его загрузкой на экран:

import { Injectable } from '@angular/core';
import { Resolve } from '@angular/router';
import { HttpClient } from "@angular/common/http";
import { tap } from "rxjs/operators";

@Injectable({
  providedIn: 'root'
})
export class DataService implements Resolve<any> {
  constructor(private _http: HttpClient) {
  }
  resolve() {
    return this._http.get("https://5a530e1477e1d20012fa066a.mockapi.io/employeedata");
  }
}

В этом коде мы создали «DataService», реализующий интерфейс «Resolve». А раз мы реализуем интерфейс, нужно определить функцию «resolve», которая возвращает «Promise»/«Observable» или «Object Data». Теперь этот сервис можно использовать для предварительной выборки данных перед загрузкой компонента на странице приложения.

Добавляем маршруты в модуль на Angular

После создания сервиса нужно настроить маршруты, указав данные, необходимые для предварительной выборки по каждому компоненту. Посмотрим, как можно изменить маршруты.

import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { AboutComponent } from './about/about.component';
import { HeaderComponent } from './header/header.component';
import { HelpComponent } from './help/help.component';
import { DataService } from "./data.service";

const routes: Routes = [
  {
    path: "", 
    component: HeaderComponent, 
    resolve: {
      employees: DataService
    }},
  {path: "about", component: AboutComponent},
  {path: "help", component: HelpComponent}

];

@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule]
})
export class AppRoutingModule { }

В этом коде мы определяем маршруты для приложения, предоставляя ключ «resolve», содержащий объект, который будет использоваться для извлечения данных. У объекта в качестве ключа «employee», а в качестве значения  —  «DataService».

Вызывается функция «resolve» с «DataService», и сначала резолвятся возвращаемые «Promise»/«Observable». После этого загружается компонент. Данные, извлечённые из API, присваиваются объекту «employees». Данные извлекаются внутри компонента с помощью следующего кода.

Подписываемся на зарезолвенные данные

import { Component, OnInit } from '@angular/core';
import { ActivatedRoute, ActivatedRouteSnapshot } from '@angular/router';

@Component({
  selector: 'app-header',
  templateUrl: './header.component.html',
  styleUrls: ['./header.component.css']
})
export class HeaderComponent implements OnInit {

  empList: any[] = [];

  constructor(private _routes: ActivatedRoute) { }

  ngOnInit(): void {
    this._routes.data.subscribe((response: any) => {
      this.empList = response.employees;
    })
  }
}

Для получения зарезолвенных данных в приложении нужно добавить «ActivatedRoute» в конструктор. Так как функция «DataService» «resolve» возвращает «Observable». Мы можем подписаться на «this._routes.data». Таким образом будут зарезолвлены и возвращены все данные, которые значатся в ключе «resolve» указанных выше маршрутов.

Код выше возвращает список сотрудников из API, указанного в классе «DataService». Он будет доступен в ключе «employees» после того, как мы подпишемся на данные.

Рабочий код доступен по ссылке.

Читайте также:

Читайте нас в Telegram, VK и Яндекс.Дзен


Перевод статьи Mayank Gupta: Angular Resolver for Prefetching Data

Предыдущая статьяРабота с панелью индикаторов. Руководство программиста Python.Часть 2
Следующая статьяРабота с панелью индикаторов. Руководство программиста Python. Часть 3