从defer返回shareReplay是否有意义?

时间:2018-07-30 20:55:12

标签: angular rxjs reactivex reactive-extensions-js

我试图在自己的示例应用程序的身份验证例程中使用observables,而我正在构建该示例程序来学习ReactiveX,同时在查找示例的过程中发现了一个简洁且在代码中得到很好评论的要点(@alxhub,谢谢!)显示了如何组织身份验证服务以及拦截器,但是我可能无法掌握其中的经验,这可能是由于经验所致。 代码的相关部分是:

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为每个observable创建一个单独的observer,那么为什么还要打扰shareReplay?在什么情况下新创建的observer上会有多个observable

现在,我想在出现401的情况下显示一个登录对话框,但是对于一批请求,只显示一个对话框,看来shareReplay是可行的,所以我想将对话框打开的代码放在doRefreshToken中,但是如果将对话框打开的代码放在defer中,我会得到与我假定的未经身份验证的请求一样多的对话框,那么我应该如何组织它?

1 个答案:

答案 0 :(得分:0)

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

您可以创建如下所示的可观察对象,并将其分配给变量并附加到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;
})