【问题标题】:error handling with http interceptor not working in Angularhttp拦截器的错误处理在Angular中不起作用
【发布时间】:2020-07-13 05:34:55
【问题描述】:

我正在开发 Angular 8

我正在尝试通过 Interceptor 集中错误处理

我的拦截器代码正在运行,但没有返回任何错误

import {
    HttpEvent,
    HttpInterceptor,
    HttpHandler,
    HttpRequest,
    HttpResponse,
    HttpErrorResponse
   } from '@angular/common/http';
   import { Observable, throwError } from 'rxjs';
   import { retry, catchError } from 'rxjs/operators';
import { RestService } from './restservice';
import { Injectable } from '@angular/core';
import { Router } from '@angular/router';


@Injectable()
   export class HttpErrorInterceptor implements HttpInterceptor {

    constructor(private rest : RestService , private route : Router){}



    intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
      // console.log('jcsjdsjd');
      // console.error('xjxfjb');
      // console.log(request);
      // console.log(next);
      return next.handle(request).pipe(catchError(err => {
        console.log(err);
          if (err.status === 401) {
              // auto logout if 401 response returned from api
              // this.authenticationService.logout();
              location.reload(true);
          }

          const error = err.error.message || err.statusText;
          return throwError(error);
      }))
  }
} 

我还在app.module.ts的Providers中定义了拦截器

  providers: [RestService  , AuthGuard ,   commonRest    ,  {
    provide: HTTP_INTERCEPTORS,
    useClass: HttpErrorInterceptor,
    multi: true
  }],

我收到错误 403 的请求的响应是:

    {
  "messagecode": 403,
  "message": "not valid token!"
}

【问题讨论】:

  • 您是否尝试过使用 tap() 方法并检查是否 (err instanceof HttpErrorResponse) ?
  • @BrianDucca 你能分享一个使用 tap() 的虚拟代码
  • 当然:return next.handle(request).pipe( tap(() =&gt; {},(err: any) =&gt; { if (err instanceof HttpErrorResponse) { if (err.status === 401) { //do your thing } } })); 并添加 import import {tap} from 'rxjs/operators';
  • @BrianDucca 我用你的代码试过了 ->>>> 拦截(请求:HttpRequest,下一个:HttpHandler):Observable> { console.log(request);控制台.log(下一个); return next.handle(request).pipe( tap(() => {},(err: any) => { console.log(err); if (err instanceof HttpErrorResponse) { console.log(err); if ( err.status === 401) { console.log("这是 401"); } } })); } >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>> 但是 next.handle(request) 中的控制台在错误 403 上没有返回任何内容
  • 也许问题是你如何在你的 api 中返回你的错误?在我的情况下,该代码运行良好,我有一个 spring-boot API (Java) 和 Angular 8 前端应用程序。你的 api 是用什么做的?

标签: angular angular8 angular-httpclient angular-http-interceptors


【解决方案1】:

要在全局范围内使用拦截器并且提供程序位于核心模块中,应在拦截器顶部添加 @Injectable({ providedIn: 'root' }) ,如此处https://stackblitz.com/edit/angular-http-interceptor-working-for-lazy-loaded-module?file=src/app/core/token-interceptor.service.ts

【讨论】:

  • 我不确定使用providedIn: 'root' 是否可以提供“全局”拦截器。应为拦截器提供HTTP_INTERCEPTORS 令牌。原因如下:github.com/angular/angular/blob/master/packages/common/http/src/…
  • 当你使用惰性模块时,这是我让它工作的唯一方法。您可以在示例中看到我在核心模块中使用 HTTP_INTERCEPTORS
  • 我确实注意到了。但我不明白你为什么还要添加“providedIn”。我可能遗漏了什么
【解决方案2】:

确保您的 API 以以下格式返回 JSON 响应,

{
   "status" : "403",
   "message" : "Session expired"
}

以下对我有用(我在下面的示例中使用tap,以防您想从成功的 JSON 响应中提取某些内容)。

可以在catchError 部分处理错误。请参阅,为403401 提供error.status 示例。随意自定义该部分。

intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {

    return next.handle(request).pipe(
      tap(evt => {
        if (evt instanceof HttpResponse) {
          
        }
      }),
      catchError(err => {
        if (err.status === 403) {
          // Handle 403 specific errors
        } else if (err.status === 401) { 
          // Handle 401 specific errors
        }

        const error = err.error.message || err.statusText;
        return throwError(error);
      }), map(event => {
        if (event instanceof HttpResponse) {

        }
        return event;
      }), catchError(this.handleError));
  }

  private handleError(error: HttpErrorResponse) {
    if (error.error instanceof ErrorEvent) {
      // A client-side or network error occurred. Handle it accordingly.
      console.error('An error occurred:', error.error.message);
    } else {
      // The backend returned an unsuccessful response code.
      // The response body may contain clues as to what went wrong,
      // console.error(
      //   `Backend returned code ${error.status}, ` +
      //   `body was: ${error.error}`);

      // TODO :  do the logout here.
      // console.log(
      //   `Backend returned code ${error.status}, ` +
      //   `body was: ${error.error}`);
      // this.router.navigate(['/login'], { queryParams: { returnUrl: '' }});
    }
    // return an observable with a user-facing error message
    return throwError(error);

  }

我希望这对某人有所帮助。

谢谢。

【讨论】:

    猜你喜欢
    • 2016-09-20
    • 1970-01-01
    • 1970-01-01
    • 2019-04-22
    • 1970-01-01
    • 1970-01-01
    • 2023-03-13
    • 2018-11-04
    • 2016-08-30
    相关资源
    最近更新 更多