【问题标题】:Angular6 HttpClient catchError not workingAngular6 HttpClient catchError 不起作用
【发布时间】:2018-06-10 10:01:45
【问题描述】:

CatchError 在 401 响应中被完全忽略。

我有处理 oauth2 身份验证的 httpInterceptor。

相关代码为:

import { filter, take, switchMap, map, catchError } from 'rxjs/operators';
//ommited
if (authService.hasRefreshToken()) {
    return authService.doRefreshToken().pipe(switchMap(tokenResponse => {
            const accessToken = tokenResponse['access_token'];
            this.tokenSubject.next(accessToken);
            return <Observable<HttpEvent<any>>> next.handle(this.addToken(req, accessToken));
        }), catchError((err: any, caught: any) => {
            console.log(err)
            return Observable.throw(err);
        })
    )
}

AuthService 类:

export class AuthService {
    doRefreshToken() {
        //ommited
        return this.httpClient.post(environment.baseUrl + this.tokenEndpoint, null, requestOptions).pipe(
            map(tokenResponse => {
                this.saveToken(tokenResponse);
                return tokenResponse;
            }),
            catchError((err: any, caught: Observable<Object>) => {
                //refreshing token failed (refrech token invalid or expired) redirect to login and wipe everything
                this.logout();
                return Observable.throw(err);
            }));
    }
}

对于 200 响应一切正常,但完全忽略 401 错误。 我是否以错误的方式使用了这个新的 catchError ?

附:这段代码在普通的旧 catch 上运行得很好,但是现在当我迁移到 angular6 管道和 catchError 时,同样的东西就不起作用了。

编辑:

catchError 上的断点显示

"SyntaxError: 输入意外结束 在 AuthService.push../src/app/common/auth/auth.service.ts.AuthService.doRefreshToken

服务器的实际响应是:

{
 "error" : "invalid_token",
 "error_description" : "Refresh token expired"
}

标题:

 Request Method: POST
 Status Code: 401 

【问题讨论】:

  • doRefreshToken() 效果好吗?
  • doRefreshToken() 中 catchError 上的断点显示消息处输入意外结束。这个方法在response为200且token更新成功的情况下确实很好用。
  • @SeaBiscuit 你有没有找到解决方案?我遇到了同样的问题,400 响应没有进入 catchError...
  • 并非如此。在我升级到 Angular 6 后它刚刚停止工作。幸运的是,我们仍在开发中,所以我将这个问题推到了积压的末尾,并希望有人能在这里发布一些东西 :)

标签: angular rxjs


【解决方案1】:

我遇到了同样的问题,即 catchError 函数被完全忽略。由于官方Angular documentation 中描述的@SeaBiscuit 使用的这个简单而直接的代码不起作用,我放弃了这种处理错误响应的方法,而是查看了HttpInterceptors。这很有效!

我受到 Luuk Gruijs 在他的文章 Global HTTP error catching in Angular 4.3+ 中的指导的启发,将下面显示的 ErrorInterceptor 添加到我的代码中。

诚然,下面的拦截器可能并不完美,但拦截器中处理错误最重要的部分归结为:

next.handle(request).pipe(tap(
  (event: HttpEvent<any>) => { },
  (error: any) => {
    // Handle errors here!
  }
))

下面是我实现的更详细的一瞥:

export class ErrorInterceptor implements HttpInterceptor {
  constructor() { }

  intercept (request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    if (request.method !== 'GET') {
      return next.handle(request);
    }

    const subject = new AsyncSubject<HttpEvent<any>>();

    next.handle(request)
    .pipe(
      tap((event: HttpEvent<any>) => {
        // Let HttpResponses pass through interceptor without interaction
        if (event instanceof HttpResponse) {
          subject.next(event);
          subject.complete();
        }
      }, (error: any) => {
        if (error instanceof HttpErrorResponse) {
          const errorEvent = new HttpResponse({
            body: {
              message: error.error.message,
              status: error.status,
              statusText: error.statusText
            }
          });

          subject.next(errorEvent);
          subject.complete();
        }
      })
    ).subscribe();

    return subject;
  }
}

我还修改了我的服务以接受手动创建的响应正文:

return this.http.get<MyObjI | ErrorI>(url, {params});

...ErrorI 是:

export interface ErrorI {
  message: string;
  status: number;
  statusText: string;
}

希望在拦截器中处理错误也能帮到你!

【讨论】:

    【解决方案2】:

    Observable.throw() 不能在退货声明中使用

    > Creates an Observable that emits no items to the Observer and immediately emits an error notification.

    这就是您在AuthService.doRefreshToken 上收到语法错误的原因

    Observable.throw() 抛出一个错误,这就是为什么你不能在 return 语句中使用它。

    跟下面是一样的,

    return throw Error("")
    

    你可以很容易地从你的 ESlint 得到抱怨。

    无论如何,由于这是一个老问题,您应该使用新的 API,但我希望这可以帮助使用旧 rxjs API 的用户。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-02-20
      • 2018-12-27
      • 1970-01-01
      • 2020-01-20
      • 2019-09-18
      • 2018-05-01
      • 1970-01-01
      相关资源
      最近更新 更多