Interceptor in Angular–loader and service
Video at https://www.youtube.com/watch?v=ajosuyhcKV4
I need to inform the user when the application is loading data – and when it is not loading anymore. Usually , the data comes from a backend via an HTTP call– and will be some timeout before it becomes available. So – simple – just intercept this and then show some spinning to the user, right ?
I found the documentation about interceptors at https://angular.io/api/common/http/HttpInterceptor – and you can find more searching on google / bing .
Also, my inspiration was started from here:
https://grensesnittet.computas.com/loading-status-in-angular-done-right/
But , if we intercept, how to distribute ? The services singleton in Angular will provide help
import { Injectable } from '@angular/core'; import { Subject, Observable } from 'rxjs'; @Injectable({ providedIn: 'root' }) export class LoaderService { constructor() { this.s = new Subject<boolean>(); } public s: Subject<boolean>; public loading$(): Observable<boolean> { return this.s.asObservable(); } public isLoading(b: boolean) { this.s.next(b); } }
So I have created the HttpInterceptor to call the service , like here:
import { Injectable } from '@angular/core'; import { HttpEvent, HttpInterceptor, HttpHandler, HttpRequest, HttpErrorResponse } from '@angular/common/http'; import { Observable, throwError } from 'rxjs'; import { catchError, tap, finalize } from 'rxjs/operators'; import { LoaderService } from './loader.service'; /** Pass untouched request through to the next request handler. */ @Injectable() export class LoaderInterceptor implements HttpInterceptor { private requests: HttpRequest<any>[] = []; constructor(private ls: LoaderService ) { } removeRequest(req: HttpRequest<any>) { const i = this.requests.indexOf(req); if (i >= 0) { this.requests.splice(i, 1); } this.ls.isLoading(this.requests.length > 0); } // https://grensesnittet.computas.com/loading-status-in-angular-done-right/ intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> { this.requests.push(req); this.ls.isLoading(true); return next.handle(req).pipe( finalize(() => this.removeRequest(req)) ); } }
And now it is simple to display in any page: – in the HTML
<mat-spinner *ngIf="isLoading"></mat-spinner>
and in the .ts pass in the constructor via DI
@Component({ selector: 'app-covid-navig', templateUrl: './covid-navig.component.html', styleUrls: ['./covid-navig.component.css'] }) export class CovidNavigComponent { public isLoading = false; constructor(private breakpointObserver: BreakpointObserver , private err: ErrorService , private snackBar: MatSnackBar , private ls: LoaderService) { this.err.NextError().pipe( tap(it => { this.snackBar.open(it, 'ERROR', { duration: 5000, }); }), shareReplay() ).subscribe(); this.ls.loading$().subscribe(it => this.isLoading = it); }
Simple , right ?
Leave a Reply