我正在使用RxSwift开发自己的OAuth2实现。为了验证请求,我有一个获取和存储访问令牌的Authenticator。因此,如果我有一个有效的访问令牌,Authenticator将立即返回它,否则它将向服务器执行请求。这正是accessTokenRequest()
所做的。
request = authenticator
.accessTokenRequest()
.map(toAuthorizationHeader)
.flatMap {self.actualRequest(withEndpoint: endpoint, authHeader: $0)}
问题在于,当我有多个请求身份验证的请求并且没有存储有效的访问令牌时,身份验证器也会发出多个访问令牌请求。这是不可取的,因为理想情况下,只应执行第一个访问令牌请求,并且所有后续请求应等到Authenticator完成获取访问令牌。
基本上我想序列化函数accessTokenRequest()
,就像关键区域一样。
关于如何实现这一目标的任何想法?
非常感谢!
更新
这是accessTokenRequest()
函数
func accessTokenRequest() -> Observable<OAuth2Credential> {
if let credential = self.cachedCredential where !credential.isExpired {
// All subsequent requests should already enter here and return right away
return Observable.just(credential)
}
...
// First request should reach here and request access token from the server.
return NetworkClient.AccessToken()
.doOnNext(cacheCredential)
}
答案 0 :(得分:0)
刚才看到这个问题已经存在了一段时间,所以无论如何我都会为将来真正需要这个问题的人提供答案。
有几种解决方案,让我们看看如何以不同的方式实现这一目标。
如果您不需要缓存,可以将accessTokenRequest()
转换为共享,并使用shareReplay(1)
重播可观察对象。这意味着内部observable将触发单个请求,然后将结果共享给所有订阅或连接的observable,因此更改将是:
func accessTokenRequest() -> Observable<OAuth2Credential> {
// First request should reach here and request access token from the server.
return NetworkClient.AccessToken().shareReplay(1)
}
更新的代码看起来很适合缓存解决方案,但是在这里我还会添加一个shareReplay
,我不会在每次需要这个observable时看到执行内部任务的要点,所以这边-effect得到共享。当然,如果调用失败的话,这是一个很好的解决方案,如果我还要添加一个retry
,以避免在失败后终止可观察的事件。