Similar video at https://www.youtube.com/watch?v=ajosuyhcKV4
I need to inform the user when the application is loading data with error ( i.e. the backend is giving some error back). And do it seamlessly , every time.
I found the documentation about interceptors at https://angular.io/api/common/http/HttpInterceptor”– and you can find more searching on google / bing .
Also, I have the need to display this no matter in what page – so a service will help
import { Injectable } from '@angular/core';
import { Subject, Observable } from 'rxjs';
@Injectable({
providedIn: 'root'
})
export class ErrorService {
private err: Subject<string>;
constructor() {
this.err = new Subject<string>();
}
public NextError(): Observable<string> {
return this.err.asObservable();
}
public setNextError(str: string) {
this.err.next(str);
}
}
Now the interceptor
import { Injectable } from '@angular/core';
import {
HttpEvent, HttpInterceptor, HttpHandler, HttpRequest, HttpErrorResponse
} from '@angular/common/http';
import { Observable, throwError } from 'rxjs';
import { catchError } from 'rxjs/operators';
import { ErrorService } from './error.service';
/** Pass untouched request through to the next request handler. */
@Injectable()
export class ErrorInterceptor implements HttpInterceptor {
constructor(private err: ErrorService ) {
}
intercept(req: HttpRequest<any>, next: HttpHandler):
Observable<HttpEvent<any>> {
return next.handle(req).pipe(
catchError( err => this.handleError(req, err))
);
}
private handleError(req: HttpRequest<any>, error: HttpErrorResponse) {
if (error.error instanceof ErrorEvent) {
// A client-side or network error occurred. Handle it accordingly.
const str = 'An error occurred:' + error.error.message;
console.log(str);
this.err.setNextError(str);
} else {
// The backend returned an unsuccessful response code.
// The response body may contain clues as to what went wrong,
const str =
`Backend returned code ${error.status}, ` +
`body was: ${JSON.stringify(error.error)}`;
console.log(str);
this.err.setNextError(str);
}
// return an observable with a user-facing error message
return throwError(
'Something bad happened; please try again later.');
}
}
The class itself
@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);
}
And this is all !( besides registering the interceptors in a barrelInterceptors.ts
import { HTTP_INTERCEPTORS } from '@angular/common/http';
import { ErrorInterceptor } from './ErrorInterceptor';
import { LoaderInterceptor } from './LoaderInterceptor';
/** Http interceptor providers in outside-in order */
export const httpInterceptorProviders = [
{ provide: HTTP_INTERCEPTORS, useClass: ErrorInterceptor, multi: true },
{ provide: HTTP_INTERCEPTORS, useClass: LoaderInterceptor, multi: true },
];
and register to the appmodule.ts
providers: [
httpInterceptorProviders,
]