Asynchrone Operation mit ReactiveCocoa wiederholen
Ich verwende ReactiveCocoa-Signale, um Aufrufe an das RESTful-Backend in unserem System darzustellen. Jeder RESTful-Aufruf sollte ein Token als einen der Parameter erhalten. Das Token selbst wird vom Authentifizierungs-API-Aufruf empfangen.
Alles funktioniert einwandfrei, und wir haben jetzt das Ablaufen von Token eingeführt. Wenn der API-Aufruf mit HTTP-Code 403 fehlschlägt, muss sich die Back-End-Zugriffsklasse möglicherweise selbst neu autorisieren. Ich möchte diesen Vorgang für die Aufrufer vollständig transparent machen up with:
- (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;
}
Ist das der richtige Weg?