Цепные API-вызовы Angular 5 для извлечения гигантского объекта с отчетом о прогрессе в пользовательский интерфейс - PullRequest
0 голосов
/ 21 мая 2018

Я работаю над Angular 5 Project, который должен быть быстрым и отзывчивым при получении гигантского объекта с сервера.Для ускорения работы приложения объект [Word Document] разбит на основные компоненты [Word Pages].Внутри основных компонентов есть выход для маршрутизатора, который загружает подкомпоненты [Paragraph].

Я привел пример большого объекта в виде текстового документа, который содержит страницы и абзацы.Из-за сложности получения этих данных из разных систем и большого веса этих объектов я решил объединить эти небольшие части в основной объект с именем BCA.

Когда пользователь переходит к BCA /: id /home / summary, который будет загружать данные сводного подкомпонента.тем временем на заднем плане запускается цепочка вызовов API для извлечения других частей [дом / дата, дом / загрузка, аудит / сводка и т. д.], составляющих основной объект BCA.

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

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

Не уверен, что Observable может помочь, также как я могу запустить этот список цепочек, который сообщает о своем состоянии и может отменить весь список, какой оператор использовать иесли какой-либо пример за пределами этого демонстрирует тот же сценарий.

Спасибо за вашу помощь.

1 Ответ

0 голосов
/ 21 мая 2018

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

Вот как вы можете ...

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

Я просто буду использовать простой, уродливый и прагматичный подход с использованием флагов;Вы можете сделать его более красивым и многократно используемым, если хотите.

import { Component, OnInit, OnDestroy } from '@angular/core';

import { forkJoin } from 'rxjs/observable/forkJoin';
import { finalize } from 'rxjs/operators';

import { MyService } from 'services';

export class MyComponent implements OnInit, OnDestroy {
    foo: any;
    loadingFoo: boolean = true;

    bar: any;
    loadingBar: boolean = true;

    baz: any;
    loadingBaz: boolean = true;

    constructor(private myService: MyService) {}

    ngOnInit() {
        this.sub = forkJoin([
            this.myService.getFoo().pipe(
                finalize(() => this.loadingFoo = false)
            ),
            this.myService.getBar().pipe(
                finalize(() => this.loadingBar = false)
            ),
            this.myService.getBaz().pipe(
                finalize(() => this.loadingBaz = false)
            )
        ]).subscribe((responses: any[][]) => {
            this.foo = responses[0];
            this.bar = responses[1];
            this.baz = responses[2];
        })
    }

    ngOnDestroy() {
        if (this.sub) {
            this.sub.unsubscribe();
        }
    }
}

И шаблон может выглядеть так:

<ng-container *ngIf="loadingFoo">
    <loader></loader>
</ng-container>
<ng-container *ngIf="!loadingFoo">
    <foo-component [foo]="foo"></foo-component>
</ng-container>

<ng-container *ngIf="loadingBar">
    <loader></loader>
</ng-container>
<ng-container *ngIf="!loadingBar">
    <bar-component [bar]="bar"></bar-component>
</ng-container>

<ng-container *ngIf="loadingBaz">
    <loader></loader>
</ng-container>
<ng-container *ngIf="!loadingBaz">
    <baz-component [baz]="baz"></baz-component>
</ng-container>
...