订阅无限循环

时间:2019-09-18 20:10:45

标签: angular

在刷新auth.interceptor.ts中的JWT令牌时,我试图捕获BadRequest(400),因为刷新令牌应在某个时刻过期。您可以查看下面的代码段,但是我也可以提供StackBlitz。

问题来自catchError,当我在其中进行return this.authService.logout()时。它进入无限循环,因为当我在switchMap中执行return next.handle(request);时,它继续向/api/values(实际请求)授予用户未授权,并引发了另一个错误。我做return throwError(error);时也是如此。这就是无限循环发生的地方。我确实必须订阅this.authService.logout(),因为注销用户后,我将从数据库中撤消了他的刷新令牌(HTTP帖子)。您可以在StackBlitz上看到整个代码。

return this.authService.refreshToken()
    .pipe(
      switchMap(token => {
        console.log('Token refreshed.');
        return next.handle(this.attachTokenToRequest(request, token));
      }),
      catchError(error => {
        return this.authService.logout()
          .pipe(
            switchMap(result => {
              console.log(result);
              return throwError(error); // request = /api/values, error = /api/refresh/token
              // return next.handle(request);
            })
          )
      })
    );

除了上面的内容以外,我尝试使用下面的代码捕获错误代码400,但还是一样。

if (error.status === 400 && error.error === "Cannot find that refresh token." || error.error === "Expired refresh token.") {
  console.log('400 bad request');
  return this.authService.logout()
    .pipe(
      switchMap(error => {
        return Observable.throw(error); // this should be replaced, maybe?
      })
    );
}

如上所述,我知道问题出在哪里。我不知道该如何解决。我想捕获刷新令牌何时到期或根本不存在,然后注销用户并导航到登录页面。我该怎么办?

https://stackblitz.com/edit/angular-dziwbx

1 个答案:

答案 0 :(得分:3)

您需要向后端服务器旁路拦截器发出登出请求。因此,您可以使用HttpClient创建一个新的HttpBackend,并在不希望拦截器干扰请求的情况下使用它。

@Injectable()
export class AuthService {
   private backendClient: HttpClient;

   public constructor(private httpClient: HttpClient, handler: HttpBackend) {
      this.backendClient = new HttpClient(handler);
   }

   // this API uses interceptors
   public refreshToken() {
      return this.httpClient.get(....);
   }

   // this API does not use interceptors
   public logout() {
      return this.backendClient.get(....);
   }
}