首页 > 解决方案 > 从 defer 中返回 shareReplay 有意义吗?

问题描述

我试图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创建一个单独的,那么他们为什么要费心呢?在什么场合会有不止一个新创建的?observableobservershareReplayobserverobservable

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

标签: angularrxjsreactivexreactive-extensions-js

解决方案


我认为shareReplayinrefreshToekn没有意义,因为正如您所说,它是从 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;
})

推荐阅读