Ich versuche, den ng4-loading-spinner
-Spinner für HTTP-Aufrufe anzuzeigen, die an meine API gerichtet sind.
Ich habe meinen Code auf den Beispielen in den folgenden Links aufgebaut:
Meine Angular 5-App verfügt über mehrere mehrere Module. Der HTTP-Interceptor befindet sich im Modul "Services".
Ich glaube, ich habe ein Problem mit der Abhängigkeit von Abhängigkeiten, da der Code-HTTP-Interceptor-Code nicht ausgeführt wird, wenn ich meinen Code mit Chrome Dev Tools debugge.
api-interceptor.ts
import 'rxjs/add/operator/do';
import 'rxjs/add/operator/catch'
import { Observable } from 'rxjs/Observable';
import { Injectable } from '@angular/core';
import {
HttpEvent,
HttpInterceptor,
HttpHandler,
HttpRequest,
HttpResponse
} from '@angular/common/http';
import { Ng4LoadingSpinnerService } from 'ng4-loading-spinner';
@Injectable()
export class ApiInterceptor implements HttpInterceptor {
private count: number = 0;
constructor(private spinner: Ng4LoadingSpinnerService) { }
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
this.count++;
if (this.count == 1) this.spinner.show();
let handleObs: Observable<HttpEvent<any>> = next.handle(req);
handleObs
.catch((err: any) => {
this.count--;
return Observable.throw(err);
})
.do(event => {
if (event instanceof HttpResponse) {
this.count--;
if (this.count == 0) this.spinner.hide();
}
});
return handleObs;
}
}
api.service.ts
import { Injectable, Inject } from '@angular/core';
import { Http, Response, Headers, RequestOptions } from '@angular/http';
import { Observable } from 'rxjs/Observable';
import { TokenService } from './token.service';
@Injectable()
export class ApiService {
constructor(
private http: Http,
private session: TokenService,
@Inject('BASE_URL') private baseUrl) { }
get(entityRoute: string): Observable<Response> {
let apiRoute = this.getApiRoute(entityRoute);
let options = this.generateRequestOptions();
return this.http.get(apiRoute, options);
}
post<T>(entityRoute: string, entity: T): Observable<Response> {
let apiRoute = this.getApiRoute(entityRoute);
let options = this.generateRequestOptions();
return this.http.post(apiRoute, entity, options);
}
put<T>(entityRoute: string, entity: T): Observable<Response> {
let apiRoute = this.getApiRoute(entityRoute);
let options = this.generateRequestOptions();
return this.http.post(apiRoute, entity, options);
}
private getApiRoute(entityRoute: string): string {
return `${this.baseUrl}api/${entityRoute}`;
}
private generateRequestOptions(): RequestOptions {
let headersObj = null;
let accessToken = this.session.getAccessToken();
if (accessToken) {
headersObj = {
'Content-Type': 'application/json',
'Authorization': 'Bearer ' + accessToken
};
} else {
headersObj = {
'Content-Type': 'application/json'
};
}
let headers = new Headers(headersObj);
return new RequestOptions({ headers: headers });
}
}
services.module.ts
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { HttpModule } from '@angular/http';
import { Ng4LoadingSpinnerModule } from 'ng4-loading-spinner';
import {
ApiInterceptor,
ApiService,
TokenService
} from './index';
@NgModule({
imports: [
CommonModule,
HttpModule,
Ng4LoadingSpinnerModule
],
providers: [
ApiInterceptor,
ApiService,
TokenService
]
})
export class ServicesModule { }
export * from './index';
app.module.ts
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { HTTP_INTERCEPTORS } from '@angular/common/http';
import { Ng4LoadingSpinnerModule } from 'ng4-loading-spinner';
import { BootstrapModule } from './bootstrap/bootstrap.module';
import { ServicesModule, ApiInterceptor } from './services/services.module';
import { AppComponent } from './app-component';
@NgModule({
bootstrap: [ AppComponent ],
imports: [
BrowserModule,
Ng4LoadingSpinnerModule.forRoot(),
BootstrapModule,
ServicesModule
],
providers: [
{
provide: 'BASE_URL',
useFactory: getBaseUrl
},
{
provide: HTTP_INTERCEPTORS,
useClass: ApiInterceptor,
multi: true,
}
]
})
export class AppModule {
}
export function getBaseUrl(): string {
return document.getElementsByTagName('base')[0].href;
}
Das Problem war, dass ApiService
die Http
von @angular/http
anstelle von HttpClient
von @angular/common/http
verwendete.
Die ApiInterceptor
hat also nichts zu fangen.
reportProgress: true vergessen. Das Problem ist, dass wir das Ereignis "do" diskriminieren müssen. Darüber hinaus müssen wir die Anrufe zählen, so dass der Interceptor so sein muss
contador: number = 0;
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
this.contador++;
if (this.condator==1)
this.spinner.show();
let handleObs: Observable<HttpEvent<any>> = next.handle(req);
handleObs
.catch((err: any) => { //If an error happens, this.contador-- too
this.contador--;
return Observable.throw(err);
})
.do(event => {
if (event instanceof HttpResponse) { //<--only when event is a HttpRespose
this.contador--;
if (this.contador==0)
this.spinner.hide();
}
});
return handleObs;
}
Für alle, die dieses Problem verfolgen, funktioniert der Code des OP jetzt gut, mit Ausnahme des verbleibenden Problems, das der Loader nicht zu verbergen scheint. Der Fix dazu ist subscribe für das Observable, nach der .catch .do -Kette, so
handleObs
.catch((err: any) => {
this.count--;
return Observable.throw(err);
})
.do(event => {
if (event instanceof HttpResponse) {
this.count--;
if (this.count == 0) this.spinner.hide();
}
})
.subscribe(); /* <---------- ADD THIS */
return handleObs;
Danach sollte der Code einwandfrei funktionieren und der Loader wird ausgeblendet, wenn der Zähler 0 erreicht hat. Vielen Dank an alle obigen Antworten für ihren Beitrag!