问题
I would like to intercept 401 and other errors in order to react accordingly. This is my interceptor:
import { LoggingService } from './../logging/logging.service';
import { Injectable } from '@angular/core';
import { HttpInterceptor, HttpHandler, HttpRequest, HttpEvent, HttpResponse, HttpErrorResponse } from '@angular/common/http';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/do';
@Injectable()
export class TwsHttpInterceptor implements HttpInterceptor {
constructor(private logger: LoggingService) { }
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
this.logger.logDebug(request);
return next.handle(request)
.do(event => {
if (event instanceof HttpResponse) {
this.logger.logDebug(event);
}
});
}
}
While this works well for 200 requests, it does not intercept the error respsonses
All I see in chrome's dev console is this:
zone.js:2616 GET http://localhost:8080/backend/rest/wrongurl 404 (Not Found)
Or this
zone.js:2616 GET http://localhost:8080/backend/rest/url 401 (Unauthorized)
I would like my interceptor to deal with this. What am I missing ?
回答1:
Http sends errors down the error stream of an observable so you will need to catch them with .catch (you can read more about this here).
return next.handle(request)
.do(event => {
if (event instanceof HttpResponse) {
this.logger.logDebug(event);
}
})
.catch(err => {
console.log('Caught error', err);
return Observable.throw(err);
});
回答2:
This is probably far too late for you to use, but hopefully someone else will find it useful... This is how to rewrite the above return statement to log error responses, too:
return next.handle(request).do((event: HttpEvent<any>) => {
if (event instanceof HttpResponse) {
this.logger.logDebug(event);
}
}, (error: any) => {
if (error instanceof HttpErrorResponse) {
this.logger.logDebug(error);
}
});
I'm using this same methodology to automatically send all 401 Unauthorized responses directly to our logout method (rather than checking for a 401 at each individual call to http):
return next.handle(request).do((event: HttpEvent<any>) => {
if (event instanceof HttpResponse) {
// process successful responses here
}
}, (error: any) => {
if (error instanceof HttpErrorResponse) {
if (error.status === 401) {
authService.logout();
}
}
});
It works like an absolute charm. :)
回答3:
At the time I was trying Angular 7+.
Unfortunately above solutions did not serve the job well because
.dois not directly available onHttpHandleras of RxJs 6 pipes notion; and convertingObservable to Promisedoes not stick.
Here is clean and up-to-date approach; I pipe the catchError operator and analyze the error and finally re-throw it by using throwError. Here is final shape of interceptor;
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
return next.handle(req).pipe(
catchError((error: HttpErrorResponse) => {
if (error.error instanceof ErrorEvent) {
// client-side error or network error
} else {
// TODO: Clean up following by introducing method
if (error.status === 498) {
// TODO: Destroy local session; redirect to /login
}
if (error.status === 401) {
// TODO: Permission denied; show toast
}
}
return throwError(error);
})
);
}
Hopefully this solution will help someone in future.
回答4:
To intercept Http response error in angular 6, I make a little trick converting Observable to Promise:
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
const obs = next.handle(req);
if (!window.navigator.onLine) {
// Handle offline error
this.messageService.showError('No Internet Connection');
return;
}
obs.toPromise().catch((error) => {
this.messageService.progress(false);
this.messageService.showError(error.message);
});
return obs;
}
来源:https://stackoverflow.com/questions/45367321/httpinterceptor-in-angular-4-3-intercepting-400-error-responses