我试图在请求完成时通知观察者以停止显示加载微调器
I'm trying to notify the observer when the request finished to stop showing the loading spinner
我通过注入我创建的 loadIndicatorService 的拦截器拦截请求,它工作正常,但是当我在 ngOnInit 中加载用户时,LoadIndicator 将请求视为即时请求,代码如下:
@Injectable()
export class AppHttpInterceptor implements HttpInterceptor {
constructor( private loadingIndicatorService: LoadingIndicatorService) { }
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
this.loadingIndicatorService.onStarted(request);
const currentUser = localStorage.getItem('token');
request = request.clone({
url: `${environment.apiURL}/${environment.apiVersion}/${request.url}`,
setHeaders: {
'Content-Type': 'application/json',
Authorization: `Bearer ${currentUser}`
}
});
return next.handle(request).finally(() => this.loadingIndicatorService.onFinished(request));
}
}
和服务:
@Injectable({
providedIn: 'root'
})
export class LoadingIndicatorService {
onLoadingChanged: EventEmitter<boolean> = new EventEmitter<boolean>();
/**
* Stores all currently active requests
*/
private requests: HttpRequest<any>[] = [];
/**
* Adds request to the storage and notifies observers
*/
onStarted(req: HttpRequest<any>): void {
this.requests.push(req);
this.notify();
}
/**
* Removes request from the storage and notifies observers
*/
onFinished(req: HttpRequest<any>): void {
const index = this.requests.indexOf(req);
if (index !== -1) {
this.requests.splice(index, 1);
}
this.notify();
}
/**
* Notifies observers about whether there are any requests on fly
*/
private notify(): void {
this.onLoadingChanged.emit(this.requests.length !== 0);
}
}
我建议创建一个广播加载状态的服务,该服务由加载微调器组件观察。每个 action/request 将使用此服务更新加载状态。
一个例子:
@Injectable()
export class LoaderService {
private loaderSubject = new Subject<boolean>();
constructor() {}
show() {
this.loaderSubject.next(true);
}
hide() {
this.loaderSubject.next(false);
}
select(): Observable<boolean>{
return this.loaderSubject.asObservable();
}
}
微调器组件:
@Component({
selector: 'app-loader',
template: 'YOUR SPINNER'
})
/**
* Loader Component to show a spinner when the state's show equals to true
*
*/
export class LoaderComponent implements OnDestroy, OnInit {
show = false;
private subscription: Subscription;
constructor(private loaderService: LoaderService) {}
ngOnInit() {
this.subscription = this.loaderService.select().subscribe(
(state: boolean) => {
this.show = state;
}
);
}
ngOnDestroy() {
if (this.subscription) {
this.subscription.unsubscribe();
}
}
}
你的拦截器:
@Injectable()
export class AppHttpInterceptor implements HttpInterceptor {
constructor( private loader: LoaderService) { }
intercept(request: HttpRequest, next: HttpHandler): Observable> {
this.loadingIndicatorService.show();
const currentUser = localStorage.getItem('token');
request = request.clone({
url: `${environment.apiURL}/${environment.apiVersion}/${request.url}`,
setHeaders: {
'Content-Type': 'application/json',
Authorization: `Bearer ${currentUser}`
}
});
return next.handle(request).finally(() => this.loading.hide());
}
}
我通过注入我创建的 loadIndicatorService 的拦截器拦截请求,它工作正常,但是当我在 ngOnInit 中加载用户时,LoadIndicator 将请求视为即时请求,代码如下:
@Injectable()
export class AppHttpInterceptor implements HttpInterceptor {
constructor( private loadingIndicatorService: LoadingIndicatorService) { }
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
this.loadingIndicatorService.onStarted(request);
const currentUser = localStorage.getItem('token');
request = request.clone({
url: `${environment.apiURL}/${environment.apiVersion}/${request.url}`,
setHeaders: {
'Content-Type': 'application/json',
Authorization: `Bearer ${currentUser}`
}
});
return next.handle(request).finally(() => this.loadingIndicatorService.onFinished(request));
}
}
和服务:
@Injectable({
providedIn: 'root'
})
export class LoadingIndicatorService {
onLoadingChanged: EventEmitter<boolean> = new EventEmitter<boolean>();
/**
* Stores all currently active requests
*/
private requests: HttpRequest<any>[] = [];
/**
* Adds request to the storage and notifies observers
*/
onStarted(req: HttpRequest<any>): void {
this.requests.push(req);
this.notify();
}
/**
* Removes request from the storage and notifies observers
*/
onFinished(req: HttpRequest<any>): void {
const index = this.requests.indexOf(req);
if (index !== -1) {
this.requests.splice(index, 1);
}
this.notify();
}
/**
* Notifies observers about whether there are any requests on fly
*/
private notify(): void {
this.onLoadingChanged.emit(this.requests.length !== 0);
}
}
我建议创建一个广播加载状态的服务,该服务由加载微调器组件观察。每个 action/request 将使用此服务更新加载状态。
一个例子:
@Injectable()
export class LoaderService {
private loaderSubject = new Subject<boolean>();
constructor() {}
show() {
this.loaderSubject.next(true);
}
hide() {
this.loaderSubject.next(false);
}
select(): Observable<boolean>{
return this.loaderSubject.asObservable();
}
}
微调器组件:
@Component({
selector: 'app-loader',
template: 'YOUR SPINNER'
})
/**
* Loader Component to show a spinner when the state's show equals to true
*
*/
export class LoaderComponent implements OnDestroy, OnInit {
show = false;
private subscription: Subscription;
constructor(private loaderService: LoaderService) {}
ngOnInit() {
this.subscription = this.loaderService.select().subscribe(
(state: boolean) => {
this.show = state;
}
);
}
ngOnDestroy() {
if (this.subscription) {
this.subscription.unsubscribe();
}
}
}
你的拦截器:
@Injectable()
export class AppHttpInterceptor implements HttpInterceptor {
constructor( private loader: LoaderService) { }
intercept(request: HttpRequest, next: HttpHandler): Observable> {
this.loadingIndicatorService.show();
const currentUser = localStorage.getItem('token');
request = request.clone({
url: `${environment.apiURL}/${environment.apiVersion}/${request.url}`,
setHeaders: {
'Content-Type': 'application/json',
Authorization: `Bearer ${currentUser}`
}
});
return next.handle(request).finally(() => this.loading.hide());
}
}