所以我要做的就是这个。
我通过查看this文章来完成这项工作。他们这样解决了。
- (RACSignal *)doRequestAndRefreshTokenIfNecessary:(RACSignal *)requestSignal {
return [requestSignal catch:^(NSError *error) {
// Catch the error, refresh the token, and then do the request again.
BOOL hasRefreshToken = [UserManager sharedInstance].refreshToken != nil;
BOOL httpCode401AccessDenied = error.code == -1011;
if (httpCode401AccessDenied && hasRefreshToken) {
return [[[self refreshToken] ignoreValues] concat:requestSignal];
}
return requestSignal;
}];
}
但这是抓住了。如果我使用过期的访问令牌触发多个请求,我有时会遇到有多次刷新的竞争条件。
所以我认为我可以将刷新信号保存为实例变量,并将所有后续失败的请求“链接”到该变量。但结果是刷新信号多次完成。
- (RACSignal *) refreshToken {
NSDictionary *params = @{
@"client_id": [Config clientId],
@"client_secret": [Config clientSecret],
@"grant_type": @"refresh",
@"refresh_token": [[Tokens sharedTokens] refreshToken]
};
if (self.activeRefreshSignal == nil) {
@weakify(self)
self.activeRefreshSignal = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
@strongify(self)
[[RestAPI sharedClient] POST:@"/oauth/token"
parameters:params
success:^(NSURLSessionDataTask *operation, id responseObject) {
[self extractTokensFromResponseObject:responseObject];
[subscriber sendNext:nil];
[subscriber sendCompleted];
self.activeRefreshSignal = nil;
}
failure:^(NSURLSessionDataTask *operation, NSError *error) {
[[Tokens sharedTokens] clearTokens];
[subscriber sendError:error];
self.activeRefreshSignal = nil;
}];
return nil;
}];
}
return self.activeRefreshSignal;
}
任何想法如何避免竞争条件,只做一次刷新?