我使用ReactiveCocoa信號來表示對系統中RESTful後端的調用。每個RESTful調用都應該接收一個令牌作爲參數之一。令牌本身是從認證API調用接收的。使用ReactiveCocoa重試異步操作
所有的工作都很好,現在我們引入了令牌過期,所以如果API調用失敗並且HTTP代碼爲403,後端訪問類可能需要重新授權。我想讓調用者完全透明,這是最好的我想出了:
- (RACSignal *)apiCallWithSession:(Session *)session base:(NSString *)base params:(NSDictionary *)params get:(BOOL)get {
NSMutableDictionary* p = [params mutableCopy];
p[@"token"] = session.token;
RACSubject *subject = [RACReplaySubject subject];
RACSignal *first = [self apiCall:base params:p get:get]; // this returns the signal representing the asynchronous HTTP operation
@weakify(self);
[first subscribeNext:^(id x) {
[subject sendNext:x]; // if it works, all is fine
} error:^(NSError *error) {
@strongify(self);
// if it doesn't work, try re-requesting a token
RACSignal *f = [[self action:@"logon" email:session.user.email password:session.user.password]
flattenMap:^RACStream *(NSDictionary *json) { // and map it to the other instance of the original signal to proceed with new token
NSString *token = json[@"token"];
p[@"token"] = token;
session.token = token;
return [self apiCall:base params:p get:get];
}];
// all signal updates are forwarded, we're only re-requesting token once
[f subscribeNext:^(id x) {
[subject sendNext:x];
} error:^(NSError *error) {
[subject sendError:error];
} completed:^{
[subject sendCompleted];
}];
} completed:^{
[subject sendCompleted];
}];
return subject;
}
這是正確的方法嗎?
感謝您的回答!除了'p'變量沒有更新的事實,我看起來都很好。在我的代碼片段中,調用'[self apiCall:params:get:]'兩次調用*不同的*值'p'(第二次調用發生在更新後的令牌中)。在你的代碼片段中,這可能會也可能不是這樣(取決於代碼的不同部分是否共享對象引用)。什麼是使參數更新顯式的好方法? –
'p'在上面的示例中以相同的方式更新。只要它是一個可變的字典,塊就會看到更新。如果您想更明確一些,可以將'apiCall'變成一個代碼塊,其中包含''p'字典,然後_returns_用於API調用的'RACSignal'。 –
如果你想嘗試獲取令牌固定次數或重複直到它是正確的?我正在考慮你從用戶那裏獲得憑據的情況,因此想要讓用戶有一兩次機會來糾正或停止前進,直到他們做對了。 – Ayal