2017-08-14 3 views
2

Ich habe ein paar asynchrone Netzwerkaufgaben, die ich auf meiner App ausführen muss. Angenommen, ich benötige 3 Ressourcen, die ich von einem Server abrufen muss, rufen Sie sie unter A, B und C an. Nehmen wir an, ich muss die Ressource A zuerst holen, bevor ich entweder B oder C geholt habe. Manchmal möchte ich zuerst B holen, andere Male C zuerst. RechtsSwift führen asynchrone Aufgaben in der Reihenfolge

jetzt, ich habe nur eine langkettige Verschluss wie so:

func fetchA() { 
    AFNetworking.get(completionHandler: { 
    self.fetchB() 
    self.fetchC() 
    }) 
} 

Das ist für jetzt funktioniert, aber die offensichtliche Einschränkung ist, ich habe hart codiert die Reihenfolge der Ausführung in den Abschluss-Handler fetchA. Nun, sage ich möchte nur fetchC nach fetchB hat in diesem Abschluss-Handler beendet, würde ich meine Implementierung gehen ändern für fetchB ...

Im Wesentlichen würde Ich mag wissen, ob es irgendeine magische Art und Weise zu tun ist so etwas wie:

let orderedAsync = [fetchA, fetchB, fetchC] 
orderedAsync.executeInOrder() 

wo fetchA, fetchB und fetchC sind alle Asynchron-Funktionen, aber fetchB wird nicht ausgeführt, bis fetchA usw. beendet ist. Vielen Dank!

+1

Nicht verwandt, aber Sie könnten Alamofire anstelle von AFNetworking verwenden. Es ist vom selben Autor, aber eine schnelle Lösung. Aber Sie müssen noch etwas tun, um asynchrone Aufgaben zu bearbeiten, entweder PromiseKit, eine asynchrone "Operation" - Unterklasse zum Umbrechen der Anfragen oder Ähnliches. – Rob

+0

Wenn Sie innerhalb von AFNetworking geblieben sind, habe ich einen kleinen "NSOperation" -Wrapper dafür gemacht: https://github.com/robertmryan/AFHTTPSessionOperation – Rob

Antwort

2

Sie können eine serielle DispatchQueue gemischt mit DispatchGroup.enter(), DispatchGroup.leave() und DispatchGroup.modify() verwenden, daß nur ein Ausführungsblock zu einem Zeitpunkt ausgeführt werden soll gewährleisten.

let serialQueue = DispatchQueue(label: "serialQueue") 
let group = DispatchGroup() 
group.enter() 
serialQueue.async{ //call this whenever you need to add a new work item to your queue 
    fetchA{ 
     //in the completion handler call 
     group.leave() 
    } 
} 
serialQueue.async{ 
    group.wait() 
    group.enter() 
    fetchB{ 
     //in the completion handler call 
     group.leave() 
    } 
} 
serialQueue.async{ 
    group.wait() 
    group.enter() 
    fetchC{ 
     group.leave() 
    } 
} 

Oder wenn Sie berechtigt sind, eine 3rd-Party-Bibliothek zu verwenden, verwenden PromiseKit, macht es Handhabung und vor allem Verkettungs async Methoden Weise einfacher als alles, was GCD bietet. Weitere Informationen finden Sie auf der Seite official GitHub. Sie können ein Asynchron-Methode mit einem Abschluss-Handler in einem Versprechen wickeln und ketten sie zusammen wie folgt aus:

Promise.wrap(fetchA(completion:$0)).then{ valueA->Promise<typeOfValueB> in 
    return Promise.wrap(fetchB(completion:$0) 
}.then{ valueB in 

}.catch{ error in 
    //handle error 
} 

Auch werden alle Fehler durch Ihre Versprechen propagiert.

+1

Dies funktioniert nicht, wenn fetchA/B/C selbst asynchron sind. – dan

+1

Enthalten eine DispatchGroup in Die Lösung, jetzt funktioniert es sicher. Außerdem wurde PromiseKit als Alternative bereitgestellt. –

+0

Versprechen sind der Weg zu gehen! –

Verwandte Themen