首页 文章

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

提问于
浏览
15

我想 to intercept 401 and other errors 以便做出相应的反应 . 这是我的拦截器:

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个请求, it does not intercept the error respsonses

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

zone.js:2616 GET http:// localhost:8080 / backend / rest / wrongurl 404(Not Found)

或这个

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

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

4 回答

  • 1

    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);
      });
    
  • 0

    这对你来说可能为时已晚,但希望其他人会觉得它很有用......这就是如何重写上面的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();
        }
      }
    });
    

    它的工作就像一个绝对的魅力 . :)

  • 29

    那时我正在尝试Angular 7 .

    不幸的是,上述解决方案并不能很好地完成这项工作,因为在RxJs 6管道概念中,HttpHandler不能直接使用.do;并将Observable转换为Promise并不坚持 .

    这是干净和最新的方法;我 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);
          })
        );
      }
    

    希望这个解决方案将来会帮助某人 .

  • 7

    为了拦截角度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;
    }
    

相关问题