使用新令牌重播失败的请求

问题描述 投票:0回答:1

刷新令牌后,我尝试重播失败的请求。 以下this 作为指导。

我的http拦截器:

isRefreshingToken: boolean = false
tokenSubject: Subject<void> = new Subject<void>()

intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
  return next.handle(this.tokenRequest(req)).pipe(
    catchError((error) => {
      if (error instanceof HttpErrorResponse) {
        if (error.status === HttpStatusCode.Unauthorized) {
          if (!this.isRefreshingToken) {
            this.isRefreshingToken = true
            this.dialog.open(LoginDialog).afterClosed().subscribe(() => {
              // at this point there is a new token in my token service
              this.isRefreshingToken = false
              this.tokenSubject.next()
            })
          }
          
          return this.tokenSubject.pipe(
            switchMap(() => {
              return next.handle(this.tokenRequest(req))
            })
          )
        }
      }

      return throwError(() => error)
    })
  )
}

tokenRequest(req: HttpRequest<any>): HttpRequest<any> {
  const token = // get token from service
  return req.clone({ headers: req.headers.set('Authorization', `Bearer ${token}`) });
}

这是有效的,通过对话框登录后,失败的请求将被重播。 然而,订阅永远不会从发出原始请求的客户端触发。

httpService.getStuff().subscribe(() => {
  // I am never called if the error request that was caught in the interceptor was retried
})

因此,在出现错误和令牌刷新的情况下,我从 http 拦截器返回的可观察值似乎不正确。 有什么想法吗?

angular angular-httpclient angular-http-interceptors
1个回答
0
投票

拦截器不会等待所有异步操作完成,它可能只需要第一次发射。您需要在组件级别编写此代码才能使其工作。建议减少过于复杂的代码并给出

retry(1)
这可以简化您的要求。

api$.pipe(
  retry(1)
  ).subscribe({
  next: (val: any) => console.log(val),
  error: (error: any) => console.log(error),
  complete: () => console.log('complete'),
});
© www.soinside.com 2019 - 2024. All rights reserved.