我在调用远程 Web API 的应用程序中使用 ReactiveCocoa。但在从给定的 API 主机检索任何东西之前,应用程序必须提供用户的凭据并检索 API 令牌,然后使用该令牌对后续请求进行签名。
我想抽象出这个身份验证过程,以便每当我进行 API 调用时它都会自动发生。假设我有一个包含用户凭据的 API 客户端类。
// getThing returns RACSignal yielding the data returned by GET /thing.
// if the apiClient instance doesn't already have a token, it must
// retrieve one before calling GET /thing
RAC(self.thing) = [apiClient getThing];
如何使用 ReactiveCocoa 透明地导致对 API 的第一个(也是唯一一个)请求进行检索,并作为副作用,在发出任何后续请求之前安全地存储 API 令牌?
这也是我可以使用combineLatest:
(或类似方法)启动多个同时请求并且它们都将隐式等待检索令牌的要求。
RAC(self.tupleOfThisAndThat) = [RACSignal combineLatest:@[ [apiClient getThis], [apiClient getThat]]];
此外,如果在进行 API 调用时检索令牌请求已经在进行中,则该 API 调用必须等待直到检索令牌请求完成。
我的部分解决方案如下:
基本模式将用于将flattenMap:
产生令牌的信号映射到给定令牌的信号,该信号执行所需的请求并产生 API 调用的结果。
假设一些方便的扩展NSURLRequest
:
- (RACSignal *)requestSignalWithURLRequest:(NSURLRequest *)urlRequest {
if ([urlRequest isSignedWithAToken])
return [self performURLRequest:urlRequest];
return [[self getToken] flattenMap:^ RACSignal * (id token) {
NSURLRequest *signedRequest = [urlRequest signedRequestWithToken:token];
assert([urlRequest isSignedWithAToken]);
return [self requestSignalWithURLRequest:signedRequest];
}
}
现在考虑-getToken
.
- 在普通情况下,当令牌已经被检索到时,订阅会立即生成令牌。
- 如果尚未检索到令牌,则订阅将遵循返回令牌的身份验证 API 调用。
- 如果身份验证 API 调用正在进行中,添加另一个观察者应该是安全的,而不会导致身份验证 API 调用通过网络重复。
但是我不确定如何做到这一点。另外,如何以及在哪里安全地存储令牌?某种持久/可重复的信号?