Besser asynchrone Ablaufsteuerung mit Objective-C blocks
Ich bin mit AFNetworking für asynchrone Aufrufe an eine web service. Einige dieser Aufrufe müssen in Reihe geschaltet werden, wobei die Ergebnisse von call-A-by-call B die verwendet werden, durch aufrufen von C, etc.
AFNetworking Griffe Ergebnisse der asynchronen Aufrufe mit Erfolg/Misserfolg Blöcke auf die Zeit der operation erstellt:
NSURL *url = [NSURL URLWithString:@"http://api.twitter.com/1/statuses/public_timeline.json"];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
AFJSONRequestOperation *operation = [AFJSONRequestOperation JSONRequestOperationWithRequest:request success:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON) {
NSLog(@"Public Timeline: %@", JSON);
} failure:nil];
[operation start];
Diese Ergebnisse in geschachtelte async-Aufruf blockiert schnell unlesbar wird. Es ist sogar noch komplizierter, wenn die Aufgaben nicht voneinander abhängig, sondern müssen parallel ausgeführt werden und die Ausführung hängt von den Ergebnissen aller Vorgänge.
Es scheint, dass der bessere Ansatz wäre die Nutzung einer verspricht framework zu bereinigen, die Ablaufsteuerung.
Denen ich begegnet bin MAFuture aber kann nicht herausfinden, wie man am besten zu integrieren, Sie mit AFNetworking. Da der asynchrone Aufrufe könnten mehrere Ergebnisse (Erfolg/Misserfolg) und nicht über eine return-Wert es scheint nicht, wie eine ideale Passform.
Irgendwelche Hinweise oder Ideen würde geschätzt.
- Vielen Dank für diese Frage – Sie haben einige gute Antworten. Ich hatte ein wenig Mühe, es zu finden, zunächst aber, und habe hier über die Suche zu Versprechen. Dieses anti-pattern passieren kann, für alle asynchronen callback-API: es ist nicht AFNetworking bestimmten. Ich wurde durch eine Suche so etwas wie: "serialising verschachtelten block Rückrufe". Vielleicht ein paar mehr tags helfen könnte? Es könnte nur sein, mich aber! 🙂
Du musst angemeldet sein, um einen Kommentar abzugeben.
Ich noch nicht benutzt, aber es klingt wie Reaktive Kakao wurde entworfen, um zu tun genau das, was Sie beschreiben.
Erstellte ich eine leichte Lösung für dieses. Es nennt sich Sequenzer und es ist bis auf github.
Macht es chaining-API-Aufrufe (oder jedem anderen async-code) einfach und unkompliziert.
Hier ist ein Beispiel für die Verwendung von AFNetworking mit:
nil
übergeben wird, die das Versagen blockiert, so dass Fehler werden stillschweigend ignoriert (aber Fehler do führen Sie den sequencer zu stoppen und entsorgt werden, denn nichts fordert den nächsten Schritt). In meinem code habe ich eine Fehler-handler-block zur Verfügung, um die Funktion, die ausgeführt wird, dieSequencer
. Ich pass dieser Fehler-handler anstelle dernil
. Wenn es wird ein Fehler ist, ich will nicht die verbleibenden Schritte ausführen. Ich will die Fehler-block rief sofort dort an und der Sequenzer wird einfach weggeworfen am Ausgangspunkt erreicht.__block
variable vor ein Schritt (in Funktionsumfang), weisen Sie im ein Schritt, und Verwendung die variable, die in einem zukünftigen Schritt.Es war nicht ungewöhnlich, dass bei der Verwendung von AFNetworking in Gowalla Anrufe verkettet Erfolg blockiert.
Mein Rat wäre, um den Faktor der Netzwerk-Anfragen und serialisierungen, wie gut Sie können in die Klasse der Methoden, die in Ihrem Modell. Dann, für Anfragen, die brauchen, um sub-requets, Sie rufen kann, auch diejenigen Methoden, die den Erfolg blockieren.
Auch im Fall, dass Sie nicht verwenden es bereits,
AFHTTPClient
vereinfacht diese Art von komplexen Netzwerk von Interaktionen.PromiseKit nützlich sein könnte. Es scheint eines der beliebtesten Versprechen Implementierungen, und andere geschrieben haben Kategorien zu integrieren, Sie mit Bibliotheken wie z.B. AFNetworking, siehe PromiseKit-AFNetworking.
Gibt es ein Objective-C-Implementierung von CommonJS-Stil verspricht hier auf Github:
https://github.com/mproberts/objc-promise
Beispiel (aus der Readme-Datei.md)
Ich noch nicht versucht, aus dieser Bibliothek, aber es sieht 'vielversprechend' trotz dieses etwas unglücklich Beispiel. (sorry, ich konnte nicht widerstehen).
Kombinieren Sie
NSBlockOperation
mitsemaphore
zu erreichen: