繁体   English   中英

Angular HTTP 拦截器错误未刷新视图

[英]Angular HTTP interceptor error not refreshing view

我正在关注本教程https://angular-academy.com/angular-jwt/并且我的 HTTP 拦截器 class 需要一点帮助。

当我在 401(未经授权的错误)之后成功刷新令牌时,代码重试 HTTP 调用,我得到了 OK,但视图和订阅没有更新,有时我会收到以下错误:

core.js:9110 ERROR TypeError: You provided 'undefined' where a stream was expected. You can provide an Observable, Promise, Array, or Iterable.
   at subscribeTo (subscribeTo.js:27)
   at subscribeToResult (subscribeToResult.js:11)
   at CatchSubscriber.error (catchError.js:38)
   at XMLHttpRequest.onLoad (http.js:1974)
   at ZoneDelegate.invokeTask (zone-evergreen.js:391)
   at Object.onInvokeTask (core.js:34182)
   at ZoneDelegate.invokeTask (zone-evergreen.js:390)
   at Zone.runTask (zone-evergreen.js:168)
   at ZoneTask.invokeTask [as invoke] (zone-evergreen.js:465)
   at invokeTask (zone-evergreen.js:1603) (editado) 

这是我的 401 处理程序:

private handle401Error(request: HttpRequest<any>, next: HttpHandler,tokens) {
  if (!this.isRefreshing) {
    this.isRefreshing = true;
    this.refreshTokenSubject.next(null);
    return this.auth.refreshToken(tokens).pipe(
      switchMap((token: any) => {
        this.isRefreshing = false;
        this.refreshTokenSubject.next(token.token);
        this.db.removeAll('token');
        this.db.storage.set('token',token);
        return next.handle(this.addToken(request, token.token));
      })).subscribe(r => r);
  } else {
    return this.refreshTokenSubject.pipe(
      filter(token => token != null),
      take(1),
      switchMap(jwt => {
        console.log(jwt)
        return next.handle(this.addToken(request, jwt));
      }));
  }
}

所以,这里我们再次 go。

抛出该错误是因为如果错误为401 (如果我从您的第一篇文章中没记错的话),您没有在您的intercept()方法中返回可观察的对象。

您不应该在拦截器中手动订阅。 Angular 为您做到这一点。 您需要使用诸如 switchMap 之类的switchMap运算符返回一个可观察对象。 对于副作用,请使用tap运算符。

删除订阅后您的handle401Error应该是:

private handle401Error(request: HttpRequest<any>, next: HttpHandler,tokens) {
    if (!this.isRefreshing) {
      this.isRefreshing = true;
      this.refreshTokenSubject.next(null);

      return this.auth.refreshToken(tokens).pipe(
        switchMap((token: any) => {
          this.isRefreshing = false;
          this.refreshTokenSubject.next(token.token);
          this.db.removeAll('token');
          this.db.storage.set('token',token);

          return next.handle(this.addToken(request, token.token));
        }));
    } else {

      // I'm not sure about this part since to me it seems that in this block the 
      // subject it will always emit null value after the token expires and the
      // browser is refreshed because the data won't persist.
      // if I'm right use this here and should work: **return next.handle(request);**
      return this.refreshTokenSubject.pipe(
        filter(token => token != null),
        take(1),
        switchMap(jwt => {
          console.log(jwt)
          return next.handle(this.addToken(request, jwt));
        }));
    }
  }

intercept方法:

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

    if (this.authService.getJwtToken()) {
      request = this.addToken(request, this.authService.getJwtToken());
    }

    return next.handle(request).pipe(catchError(error => {
      if (error instanceof HttpErrorResponse && error.status === 401) {
        // here don't forget tor return
        return this.handle401Error(request, next);
      } else {
        return throwError(error);
      }
    }));
  }

在 next.handle 之后尝试 Remove.subscribe(r => r) 调用。 您需要返回可观察的,而不是 function 调用。

return next.handle(
    this.addToken(request, token.token)
);

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM