Предварительный загрузчик не показывает один или несколько вызовов службы http одновременно с использованием httpInterceptors?

#rxjs #angular6

#rxjs #angular6

Вопрос:

Я хочу реализовать концепцию глобального загрузчика в angular с использованием httpInterceptors, она не работает предположим, что если одновременно вызываются два вызова службы http, ‘finalize’ сработает только после завершения одного или нескольких вызовов http api, но этого не произошло, предварительный загрузчик также отображается некорректно, он скрывается после первого apiвызов завершен. Пожалуйста, предложите, что я пропустил, и скажите мне, как с этим справиться. Является ли это правильным местом для обработки глобальной ошибки и концепции предварительного загрузчика?

app.component.html

 <preloader [loading]="appService.loading"></preloader>
 

app.component.ts:

 const url1 = "https://jsonplaceholder.typicode.com/albums/1";
const url2 = "https://jsonplaceholder.typicode.com/albums/2";
forkJoin(
        this.http.get(url1),
        this.http.get(url2),
    ).subscribe(console.log);
 

HttpserviceInterceptor:

 import {
    HttpEvent,
    HttpHandler,
    HttpInterceptor,
    HttpRequest,
} from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';
import { finalize, tap } from 'rxjs/operators';
import { AppCommonService } from './app.common.service';

@Injectable()
export class HttpserviceInterceptor implements HttpInterceptor {
    constructor(
        private appService: AppCommonService,
        private notification: NotificationsWrapperService,
    ) {}
    public intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
        this.appService.showPreLoader()
        return next.handle(request).pipe(
            //tslint:disable-next-line: no-empty
            tap(() => {
            }, (error: any) => {
                this.notification.error(error);
            }),
            finalize(() => this.appService.hidePreLoader()),
        );
    }
}
 

Appcommon Service:

 public showPreloader(): void {
    //this.showPreloader$.next(true);
    this.loading = true;
}

public hidePreLoader(): void {
    //this.showPreloader$.next(false);
    this.loading = false;
}
 

Ответ №1:

Предположим, что вы выполняете два запроса. Для завершения первого требуется одна секунда, а для второго — 5 секунд. На основе предоставленного вами кода поток загрузчика будет следующим.

  • Первый запрос выполняется и this.loading имеет значение true
  • Выполняется второй запрос, и this.loading ему снова присваивается значение true
  • Первые запросы завершаются и this.loading имеют значение false (неверно)
  • Второй запрос завершается и this.loading имеет значение false

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

Поэтому, когда выполняются запросы, вы всегда должны устанавливать флаг {this.loading} в значение true и увеличивать значение this.currentNumberOfRequests на 1, а когда запросы завершаются успешно или завершаются неудачно (в идеале в предложении finally), вы должны уменьшить значение this.currentNumberOfRequests на 1. Теперь, если значение this.currentNumberOfRequests равно 0, вы должны скрыть загрузчик.