在Angular7的HTTP请求期间显示微调框

时间:2019-04-14 23:04:43

标签: angular typescript angular-ng-if

我正在尝试在Angular 7上的应用程序HTTP请求期间显示微调器。 我创建了一个HttpInterceptor类,一个加载程序服务和一个加载程序组件,以及一个表示微调器状态(显示或隐藏)的Subject。但是,在加载程序服务和加载程序组件之间似乎存在问题

当控制台输出true和false状态(下面的代码)时,HttpInterceptor似乎运行良好,但是loader服务和loader组件似乎存在问题。我已经使用ngIf指令根据主题的状态显示或隐藏微调器。

LoaderService:

import { Injectable } from '@angular/core';
import { Subject } from 'rxjs';

@Injectable({
  providedIn: 'root'
})
export class LoaderService {

  isLoading = new Subject<boolean>();

  show() {
    console.log('true');
    this.isLoading.next(true);
  }

  hide() {
    console.log('false');
    this.isLoading.next(false);
  }

  constructor() { }
}

LoaderComponent

import { Component, OnInit } from '@angular/core';
import {LoaderService} from '../loader.service';
import { Subject } from 'rxjs';

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

  isLoading: Subject<boolean> = this.loaderService.isLoading;

  constructor(private loaderService: LoaderService) { }

  ngOnInit() {
  }

}
<div *ngIf="isLoading | async " class="d-flex justify-content-center">
  <div class="spinner-border" role="status">
    <span class="sr-only">Loading...</span>
  </div>
</div>

当前,微调框根本没有显示或隐藏。当加载开始时,我只会在控制台中获得“ true”,然后在加载结束时获得“ false”。 我在app.component.html文件中包含了加载器选择器。它应该可以正常工作。我做错什么了吗?

2 个答案:

答案 0 :(得分:1)

您应该使用BehaviourSubject而不是SubjectSubject仅在调用next()时发出值-如果在服务推送该值之后初始化该组件,则将永远不会收到任何消息。

BehaviourSubject通过记住最后发出的值来解决此问题。因此,当您的模板订阅时,它可以获取最后一个值并进行比较。

答案 1 :(得分:1)

创建一个可以发出HTTP请求的布尔状态的HttpInterceptor非常棘手。可能同时发生多个并行请求,这不像为每个HttpRequest发出true / false那样简单。您只需在请求开始时发出一次 true ,但在最后请求完成时发出 false

最简单的方法是跟踪并发请求的数量。

这是我使用的拦截器。仅在启动新请求时才发出true,而在所有请求完成时才发出false。

import {HttpEvent, HttpHandler, HttpInterceptor, HttpRequest} from '@angular/common/http';
import {Injectable} from '@angular/core';
import {Observable, Subject} from 'rxjs';
import {distinctUntilChanged, finalize, map} from 'rxjs/operators';

class BusySubject extends Subject<number> {
    private _previous: number = 0;

    public next(value: number) {
        this._previous += value;
        if (this._previous < 0) {
            throw new Error('unexpected negative value');
        }
        return super.next(this._previous);
    }
}

@Injectable()
export class BusyInterceptor implements HttpInterceptor {

    private _requests: BusySubject = new BusySubject();

    public get busy(): Observable<boolean> {
        return this._requests.pipe(
            map((requests: number) => Boolean(requests)),
            distinctUntilChanged(),
        );
    }

    public intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
        this._requests.next(1);
        return next.handle(req).pipe(finalize(() => this._requests.next(-1)));
    }
}
  

p.s。可以使用scan()运算符正确地完成此操作,但是我还没有时间更新代码。