HttpInterceptor в Angular 4.3: перехват 400 ошибок
Я хотел бы перехватить 401 и другие ошибки, чтобы соответственно реагировать. Это мой перехватчик:
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);
}
});
}
}
Хотя это хорошо работает для 200 запросов, оно не перехватывает ошибки respsonses
Все, что я вижу в консоли chrome dev, это:
zone.js: 2616 GET http://localhost: 8080/backend/rest/misurl 404 (не найдено)
Или это
zone.js: 2616 GET http://localhost: 8080/backend/rest/url 401 (неавторизованный)
Я хотел бы, чтобы мой перехватчик справился с этим. Что мне не хватает?
Ответы
Ответ 1
Http
посылает ошибки вниз поток ошибок наблюдаемой так что вам нужно будет поймать их с .catch
(вы можете прочитать об этом здесь).
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
Это, вероятно, слишком поздно для вас использовать, но, надеюсь, кто-то еще найдет это полезным... Вот как переписать вышеприведенный оператор возврата для ответов об ошибках журнала:
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);
}
});
Я использую эту же методологию, чтобы автоматически отправлять все 401 несанкционированные ответы непосредственно на наш метод выхода из системы (вместо проверки на 401 при каждом индивидуальном вызове на 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();
}
}
});
Он работает как абсолютный шарм. :)
Ответ 3
В то время я пробовал Angular 7+.
К сожалению, вышеприведенные решения не .do
так как .do
напрямую не доступен в HttpHandler
с точки зрения RxJs 6 pipe; и преобразование Observable to Promise
не прилипает.
Здесь чистый и современный подход; Я pipe
catchError
оператора и анализировать ошибки и, наконец, снова бросить его с помощью throwError
. Вот окончательная форма перехватчика;
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);
})
);
}
Надеемся, что это решение поможет кому-то в будущем.
Ответ 4
Чтобы перехватить ошибку ответа Http в угловом 6, я делаю небольшой трюк, переводящий 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;
}