Reputation: 2075
I am trying to create an Http interceptor to display loading in all the pages. But I am not able to dismiss the loading controller
I have followed this https://www.youtube.com/watch?v=IJWCpa_-MeU But the problem is loading is displayed infinitely.
Actually I am a bit new to these concepts. So please help me out.
I have edited my code. Please find an image of console.log value. There is a problem if you are making multiple Http request on the same page. It is creating loader even if old one exists.
@Injectable()
export class HttpRequestInterceptor implements HttpInterceptor {
constructor(
private loadingCtrl: LoadingController,
private toastCtrl: ToastController,
private alertCtrl: AlertController,
// private fakeHttp: FakeHttpService
) {}
intercept(
request: HttpRequest<any>,
next: HttpHandler
): Observable<HttpEvent<any>> {
this.loadingCtrl.getTop().then(hasLoading => {
if (!hasLoading) {
console.log("loading")
this.loadingCtrl.create({
spinner: 'circular',
translucent: true
}).then(loading => loading.present());
}
});
return next.handle(request).pipe(
catchError(err => {
if (err instanceof HttpErrorResponse) {
switch ((<HttpErrorResponse>err).status) {
case 401:
// return this.handle401Error(request, next);
// handle 401 here
console.log("401")
default:
return throwError(err);
}
} else {
return throwError(err);
}
}),
retryWhen(err => {
let retries = 1;
return err.pipe(
delay(1000),
tap(() => {
// this.showRetryToast(retries);
}),
map(error => {
if (retries++ === 3) {
throw error; // Now retryWhen completes
}
return error;
})
);
}),
catchError(err => {
// this.presentFailedAlert(err.error['msg']);
return EMPTY;
}),
finalize(() => {
console.log("hii")
this.loadingCtrl.getTop().then(hasLoading => {
if (hasLoading) {
this.loadingCtrl.dismiss();
}
});
})
);
}
Here is a simple Http request I made, but data is displayed in console.log but loading is not getting dismissed
ngOnInit() {
this.cartService.getProductDetails().subscribe(data =>{
this.products = data;
this.filter_products = this.products;
console.log(this.products)
})
Upvotes: 1
Views: 723
Reputation: 178
You are having multiple going at the same time, It's a race condition issue.. For this approach I would use a service that debounces the show & hide. this is the issue if you have multiple request going out at the same time or very close to each other..
Loading Service
import { Injectable } from '@angular/core';
import { LoadingController } from '@ionic/angular';
import { BehaviorSubject } from 'rxjs';
import { LoadingOptions } from '@ionic/core';
import { TranslateService } from '@ngx-translate/core';
import { debounceTime, distinctUntilChanged, filter, throttle } from 'rxjs/operators';
import { isNil } from 'lodash-es';
enum LoadingTypeEnum {
show,
hide,
message
}
@Injectable({
providedIn: 'root'
})
export class LoadingService {
public loading$: BehaviorSubject<{ type: LoadingTypeEnum; data?: any }> = new BehaviorSubject<any>({ type: LoadingTypeEnum.hide });
loadingState: { type: LoadingTypeEnum; data?: any } = null;
public loading: HTMLIonLoadingElement = null;
public async getLoader() {
return await this.loadingController.getTop() || null
};
private async showLoading(opts: LoadingOptions) {
if (!this.loading) {
this.loading = await this.loadingController.create(opts);
await this.loading.present();
}
}
private async hideLoading() {
if (this.loading) {
await this.loading?.dismiss();
}
this.loading = null;
}
private async messageLoading(m: string) {
if (this.loading) {
this.loading.message = m
}
}
constructor(private loadingController: LoadingController) {
const l$ = this.loading$.pipe(distinctUntilChanged(), debounceTime(200));
l$.pipe(filter(l => l.type === LoadingTypeEnum.show)).subscribe(l => this.showLoading(l.data));
l$.pipe(filter(l => l.type === LoadingTypeEnum.hide)).subscribe(l => this.hideLoading());
l$.pipe(filter(l => l.type === LoadingTypeEnum.message)).subscribe(l => this.messageLoading(l.data));
}
show(opts?: LoadingOptions) {
if (isNil(opts)) opts = {
message: 'Please Wait';
};
this.loading$.next({ type: LoadingTypeEnum.show, data: opts })
}
hide() {
this.loading$.next({ type: LoadingTypeEnum.hide })
}
message(m: string) {
this.loading$.next({ type: LoadingTypeEnum.message, data: m })
}
}
Interceptor
@Injectable()
export class HttpRequestInterceptor implements HttpInterceptor {
constructor(private loading: LoadingService) {
}
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
this.loading.show();
return next.handle(request).pipe(
catchError(err => {
if (err instanceof HttpErrorResponse) {
switch ((<HttpErrorResponse>err).status) {
case 401:
console.log("401")
default:
return throwError(err);
}
} else {
return throwError(err);
}
}),
retryWhen(err => {
let retries = 1;
return err.pipe(
delay(1000),
tap(() => {
// this.showRetryToast(retries);
}),
map(error => {
if (retries++ === 3) {
throw error; // Now retryWhen completes
}
return error;
})
);
}),
catchError(err => EMPTY),
finalize(() => this.loading.hide()))
}
}
Upvotes: 1