在所有子组件和子子组件中的数据到达Angular中之前,显示加载栏的最佳方法是什么

时间:2019-06-20 18:21:57

标签: angular

我有带有加载条的组件,该加载条显示和隐藏名为isLoading的布尔变量。例如:

ngOnInit() {
  this.isLoading = true;
  this.someService.getAll().subscribe(data => { 
    // some code...
    this.isLoading = false;
  });
}
<loading-bar *ngIf="isLoading"></loading-bar>

但是,当主组件中有子组件并且从中加载数据时,我有一个问题。加载栏应位于主组件中,并且仅在来自所有子组件的数据到达时才隐藏。实现此目标的最佳方法是什么。

3 个答案:

答案 0 :(得分:2)

您可以使用HttpInterceptor来感知应用程序中正在进行的任何HTTP活动,并创建一个在其中保留HTTP活动标志的服务。现在,在您的根组件中,只需检查该标志并显示一个加载微调器即可。这样,您不必分别处理每个子组件和子组件的加载栏的显示。

HTTPInterceptor和相关服务的代码应如下所示。

import { Injectable } from '@angular/core';
import { Observable, of, throwError } from 'rxjs';
import {
  HttpEvent,
  HttpHandler,
  HttpInterceptor,
  HttpRequest
} from '@angular/common/http';

import { BehaviorSubject } from 'rxjs';
import { catchError, finalize, map } from 'rxjs/operators';

@Injectable()
export class HTTPStatus {
  private requestInFlight$: BehaviorSubject<boolean>;
  constructor() {
    this.requestInFlight$ = new BehaviorSubject(false);
  }

  setHttpStatus(inFlight: boolean) {
    this.requestInFlight$.next(inFlight);
  }

  getHttpStatus(): Observable<boolean> {
    return this.requestInFlight$.asObservable();
  }
}

@Injectable()
export class HTTPListener implements HttpInterceptor {
  constructor(private status: HTTPStatus) {
  }

  intercept(
    req: HttpRequest<any>,
    next: HttpHandler
  ): Observable<HttpEvent<any>> {
    return next.handle(req).pipe(
      map(event => {
        this.status.setHttpStatus(true);
        return event;
      }),catchError(error => {
        return Observable.throw(error);
      }),
      finalize(() => {
        this.status.setHttpStatus(false);
      })
    )
  }
}

在您的根应用程序组件中注入HTTPStatus服务。

  HTTPActivity: boolean;

  constructor(private httpStatus: HTTPStatus) {
    this.httpStatus.getHttpStatus().subscribe(status => { this.HTTPActivity = status; });
  }

现在,在组件的.html部分中,您可以通过检查HTTPActivity布尔变量来显示/隐藏加载栏或微调器。

<div id="preloader" [hidden]=!HTTPActivity>
  <div id="loader"></div>
</div>

当然,您必须在模块的providers数组中注册HTTPListener和HTTPStatus服务。

谢谢。

答案 1 :(得分:1)

您可以为每个子组件创建isLoaded标志。 然后,通过服务共享标记状态到您的父组件。父组件的isLoaded标志将是孩子的isLoaded的组合

答案 2 :(得分:1)

我们放在整个应用程序本身上的装载程序不是吗?

您需要“实现” HttpInterceptor并在其中使用加载器,方法是将这两者与加载器服务一起附加。

这是HttpInterceptor的示例实现。

@Injectable()
export class LoaderInterceptor implements HttpInterceptor {
    constructor(public loaderService: LoaderService) { }
    intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
        this.loaderService.show();
        return next.handle(req).pipe(
            finalize(() => this.loaderService.hide())
        );
    }
}

您可以详细了解here

您也可以在上面的LoaderInterceptor中使用计数器变量。显然,这是一个主题,您将根据此值向LoaderService发出(在根据调用启动/完成的调用递增/递减之后),其中show变量将在计数器为{大于0,反之亦然。