【问题标题】:Does it make sense to return shareReplay from defer?从 defer 中返回 shareReplay 有意义吗?
【发布时间】:2018-07-30 20:55:11
【问题描述】:

我试图在我正在构建的示例应用程序的身份验证例程中使用observables 来学习ReactiveX,同时在寻找示例时,我发现了一个简洁且代码内注释的要点 (@987654321 @,谢谢!)这显示了如何组织身份验证服务和拦截器,但我无法理解那里发生的事情,可能是由于经验的运气...... 代码的相关部分是:

this.refreshToken = Observable.defer(() => {
  // Defer allows us to easily execute some action when the Observable
  // is subscribed. Here, we set the current token to `null` until the
  // refresh operation is complete. This ensures no requests will be
  // sent with a known bad token.
  this.subject.next(null);

return this
  // Next, we refresh the token from the server.
  .doRefreshToken()
  // Set it as the active token.
  .do(token => this.subject.next(token))
  // Drop the value, ensuring this Observable only completes when
  // done and doesn't emit.
  .ignoreElements()
  // Finally, share the Observable so we don't attempt multiple
  // refreshes at once.
  .shareReplay();
});

然后像这样在拦截器中使用:

.catch((err, restart) => {
  // If the request is unauthorized, try refreshing the token before restarting.
  if (err instanceof HttpErrorResponse && err.status === 401) {
    return Observable.concat(this.auth.refreshToken, restart);
  }
  throw err;
})

据我了解defer 为每个observer 创建一个单独的observable,那么他们为什么要打扰shareReplay?什么情况下新创建的observable上会有多个observer

现在,我想在401的情况下显示一个登录对话框,但对于一批请求只有一个,而且似乎shareReplay是要走的路,所以我想把对话框打开doRefreshToken 内的代码,但如果它在 defer 内,我会得到与我推测的未经身份验证的请求一样多的对话框,那么我应该如何组织它?

【问题讨论】:

    标签: angular rxjs reactivex reactive-extensions-js


    【解决方案1】:

    我认为refreshToekn 中的shareReplay 没有意义,因为正如您所说,它是从每次创建新流的 defer 发出的。我假设有或没有它,代码将运行相同。

    您可以像下面这样创建一个 observable 并将其分配给一个变量并附加到 concat。这个shareReplay 只会发出一次。

    const openDialog=
       of(true).pipe(map(e=>{
     console.log("open dialog") 
     return e 
    }),shareReplay(1))
    

    并在捕获中

    .catch((err, restart) => {
      // If the request is unauthorized, try refreshing the token before restarting.
      if (err instanceof HttpErrorResponse && err.status === 401) {
        return Observable.concat(this.auth.refreshToken,openDialog, restart);
      }
      throw err;
    })
    

    【讨论】:

    • 感谢分享,但我不确定我是否明白你的想法,你concat openDialogrefreshToken 之后,这样如果我理解正确,对话框只会打开应用程序的生命周期中只有一次,但如果我们有多个失败的请求,令牌将被刷新几个计时器......
    • 是的,你是对的,你可以像 openDialog 一样将 refreshToken() 和 shareReplay() 保存到另一个变量(但不能使用 defer())。
    猜你喜欢
    • 2013-11-24
    • 2016-06-18
    • 2011-02-02
    • 1970-01-01
    • 1970-01-01
    • 2021-04-17
    • 1970-01-01
    • 2019-08-11
    • 1970-01-01
    相关资源
    最近更新 更多