使用HttpInterceptor添加加载屏幕

时间:2018-03-01 11:51:15

标签: angular typescript angular5

这是我的LoadingScreenService:

    import { Inject, Injectable } from '@angular/core';
import { DOCUMENT } from '@angular/common';
import { animate, AnimationBuilder, AnimationPlayer, style } from '@angular/animations';
import { NavigationStart, NavigationEnd, Router, NavigationCancel } from '@angular/router';

@Injectable()
export class LoadingScreenService {

  private loadingScreenEl: HTMLElement = null;
  private player: AnimationPlayer;

  private isEnabled = false;
  private isShowing = false;
  private isHiding = false;

  constructor(
    private animationBuilder: AnimationBuilder,
    @Inject(DOCUMENT) private document: any = null,
    private router: Router = null
  ) {
    if (document !== null) {
      this.loadingScreenEl = this.document.body.querySelector('#fuse-loading-screen');
    }

    if (router !== null) {
      this.router.events.subscribe((event) => {
          if (event instanceof NavigationStart) {
            setTimeout(() => {
              this.show();
            }, 0);
          }
          if (event instanceof NavigationEnd || event instanceof NavigationCancel) {
            setTimeout(() => {
              this.hide();
            }, 0);
          }
        }
      );
    }
  }

  /**
   * @param {number} wait Duration (ms) of a timeout before showing the spinner
   */
  show(wait: number = 1000) {
    if (this.isEnabled || this.isShowing) {
      return;
    }

    this.isShowing = true;
    this.player =
      this.animationBuilder
        .build([
          style({
            opacity: '0',
            zIndex : '9999'
          }),
          animate('200ms ease', style({opacity: '1'}))
        ]).create(this.loadingScreenEl);

    this.isEnabled = true;

    setTimeout(() => {
      this.player.play();

      setTimeout(() => {
        this.isShowing = false;
      }, 200);
    }, wait);

  }

  hide() {
    if (!this.isShowing
      && (!this.isEnabled || this.isHiding)) {
      return;
    }

    this.isHiding = true;
    this.player =
      this.animationBuilder
        .build([
          style({opacity: '1'}),
          animate('200ms ease', style({
            opacity: '0',
            zIndex : '-20'
          }))
        ]).create(this.loadingScreenEl);

    setTimeout(() => {
      this.isEnabled = false;
      this.player.play();

      setTimeout(() => {
        this.isHiding = false;
      }, 200);
    }, 0);
  }
}

每当我向后端发出请求时,我都会尝试使用show / hide方法。

这是我到目前为止所得到的,但我找不到一种方法将我的subscriveLoading()方法正确地放入intercept()。

   import { Injectable } from '@angular/core';
import { HttpEvent, HttpInterceptor, HttpHandler, HttpRequest } from '@angular/common/http';
import { Observable } from 'rxjs/Observable';
import { LoadingScreenService } from '../../core/services/loading-screen.service';

@Injectable()
export class LoadingInterceptor implements HttpInterceptor {

  constructor(
    private loadingScreenService: LoadingScreenService
  ) {
  }

  intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {

  }

  private subscribeLoading(): Observable<any[]> {
    this.loadingScreenService.show();

    const observable;
    observable.subscribe(() => {
      this.loadingScreenService.hide();
    }, err => {
      this.loadingScreenService.hide();
      return err;
    }); // Pass the error to other observers

    return observable;
  }
}

我是否有一些简单的方法可以使用我的LoadingScreenService来拦截每个调用,并在我等待来自后端的响应时使用show方法提供的服务?

1 个答案:

答案 0 :(得分:2)

这是一种在拦截器中使用您的服务的方法

在拦截中你开始显示你的加载器,然后你的intecept返回一个finally操作符的请求,该操作符将隐藏成功或错误

@Injectable()
export class LoadingInterceptor implements HttpInterceptor {
    constructor(
        private loadingScreenService: LoadingScreenService
    ) {
    }

    intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
        this.loadingScreenService.show();

        return next.handle(req).finally(() => {
            this.loadingScreenService.hide();
        });
    }
}

但是:如果你有两个并发请求,当第一个请求结束时,即使第二个请求没有完成,它也会隐藏加载器。

您的服务中应该有待处理请求的计数器:

@Injectable()
export class LoadingScreenService {
....
    private counter: number: 0;
...

show(wait: number = 1000) {
        this.counter++;
....
}

hide() {
        this.counter--;
        if (this.counter > 0) return;
...
}