Angular 4.3中的HttpInterceptor:拦截400个错误响应

时间:2017-07-28 07:25:21

标签: angular interceptor

我希望拦截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个请求,它不会拦截错误响应

我在chrome的开发控制台中看到的只有:

  

zone.js:2616 GET http://localhost:8080/backend/rest/wrongurl 404(不是   实测值)

或者这个

  

zone.js:2616 GET http://localhost:8080/backend/rest/url 401   (未授权)

我希望我的拦截器能够解决这个问题。我错过了什么?

4 个答案:

答案 0 :(得分:28)

Http会向观察者的错误流发送错误,因此您需要使用.catch来捕获它们(您可以阅读有关此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);
  });

答案 1 :(得分:6)

这对你来说可能为时已晚,但希望其他人会觉得它很有用......这就是如何重写上面的return语句来记录错误响应:

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 Unauthorized响应直接发送到我们的注销方法(而不是在每次调用http时检查401):

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();
    }
  }
});

它的作用就像绝对的魅力。 :)

答案 2 :(得分:2)

当时我正在尝试 Angular 7 +

  

不幸的是,上述解决方案不能很好地解决这一问题,因为从RxJs 6管道概念开始,this.props.location.state.data 无法直接在.do上使用;并且转换HttpHandler不会停留。

这是一种干净而最新的方法;我Observable to Promise pipe运算符并分析错误,最后使用catchError重新抛出错误。这是拦截器的最终形状;

throwError

希望这种解决方案将来能对某人有所帮助。

答案 3 :(得分:0)

要拦截角度6中的Http响应错误,我做了一些技巧,将Observable转换为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;
}