我正在尝试在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文件中包含了加载器选择器。它应该可以正常工作。我做错什么了吗?
答案 0 :(得分:1)
您应该使用BehaviourSubject
而不是Subject
。 Subject
仅在调用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()运算符正确地完成此操作,但是我还没有时间更新代码。