【问题标题】:How Rxjs filter postponds http calls till the criteria matches in below code?Rxjs 如何过滤延迟 http 调用,直到条件与下面的代码匹配?
【发布时间】:2019-09-20 17:34:13
【问题描述】:

如果tokenSubject 行为主体的值不为空,我有一个代码块,它返回角度拦截器的next 函数。

if (!this.tokenRefreshing) {
  this.tokenRefreshing = true;
  this.tokenSubject.next(null);
  return this.loginService.getNewRefreshToken().pipe(
    switchMap((tokenResponse: any) => {
      if (tokenResponse) {
        localStorage.setItem('jwtToken', tokenResponse.jwtToken);
        localStorage.setItem('refreshToken', tokenResponse.refreshToken.value)
        localStorage.setItem('UserName', tokenResponse.userName);
        this.tokenSubject.next(tokenResponse);
        console.log('token refreshed');
        return next.handle(this.attachAuthToken(request));
      }
      else return <any>this.loginService.userLogout();
    }),
    catchError(err => {
      this.loginService.userLogout();
      return this.handleError(err);
    }),
    finalize(() => {
      this.tokenRefreshing = false;
    })
  )
}
else {
  return this.tokenSubject.pipe(
    filter(token => token != null),
    take(1),
    switchMap(token => {
      return next.handle(this.attachAuthToken(request))
    }),
    catchError((error) => {
      this.tokenRefreshing = false;
      return this.loginService.userLogout();
    })
  )
}

我无法理解如果多个 http 调用在那里命中以及它如何在行为主体中具有令牌值之后按顺序推迟和执行所有操作是如何工作的。谁能帮我理解这一点?

【问题讨论】:

  • 此代码块之前的其他代码在哪里?

标签: angular rxjs


【解决方案1】:

首先明确一下this.handle401Error方法中的错误处理逻辑(https://angular-academy.com/angular-jwt/)

如果您正在执行这意味着您的令牌已失效,您需要获取刷新令牌。因此,假设您有 5 个 https 调用在令牌不再有效时访问此块。第一个 http 调用命中它,它改变了

this.tokenRefreshing = true;

并立即将 tokenSubject 发出为 null

  this.tokenSubject.next(null);

然后它请求新的令牌,一旦得到它,它就会在标头中设置令牌并继续传递以让原始请求通过

next.handle(this.attachAuthToken(request));

这就是第一个 http 完成的方式。

但是现在您在刷新令牌时又启动了另一个 http(第一个 http 正在进行并请求刷新令牌)。

这第二个 http 调用将运行 else 块,因为 this.tokenRefreshing 是真的,所以它会在 tokenSubject 中查看是否有任何值,而此时它没有。所以通话只会挂起/暂停,但不会被取消,因为你被过滤掉了token===null

filter(token => token != null),

所以当第一个 http 完成获取 refreshtoken 时,它会这样做

this.tokenSubject.next(tokenResponse);

这将触发第二次 http 调用以恢复后续流项目

   take(1),
    switchMap(token => {
      return next.handle(this.attachAuthToken(request))
    }),
    catchError((error) => {
      this.tokenRefreshing = false;
      return this.loginService.userLogout();
    })

希望对你有帮助。

【讨论】:

  • 好的,我知道了,但是,so the call will just hang/pause there but will not be canceled whihc 运营商使这成为可能?过滤?
  • 是的。如果令牌不为空,过滤器将只允许流继续,然后传递给完成流的 take(1)
  • stackoverflow.com/questions/58004026/… 你能看看这个问题吗?
  • 好吧,也许今天晚些时候或明天
【解决方案2】:

正如您提到的,您有一个拦截器。拦截器通常按顺序执行。一个拦截方法返回一个 observable (Observable&lt;HttpEvent&lt;any&gt;&gt;)。您现在返回一个异步主题管道映射到此 obvservable,它在您收到令牌后完成。 Angular 等待这个完成。

【讨论】:

    猜你喜欢
    • 2018-10-17
    • 1970-01-01
    • 2017-08-12
    • 1970-01-01
    • 1970-01-01
    • 2011-08-20
    • 2019-10-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多