2017-08-14 63 views
2

我需要在我的應用上執行一些異步的網絡任務。假設我有3個資源需要從服務器獲取,請撥打ABC。假設我在取得BC之前必須首先完成獲取資源A。有時候,我想先取B,其他時候先取C按順序快速執行異步任務

現在,我只是有一個長鏈閉合,像這樣:

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

這適用於現在,但明顯的限制是我硬編碼的執行順序到完成處理程序fetchA。現在,說我只想fetchCfetchB後,在完成處理程序已經完成,我不得不去改變我的fetchB實現...

從本質上講,我想知道是否有一些神奇的方式做是這樣的:

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

其中fetchAfetchBfetchC都是異步的功能,但fetchB不會執行,直到fetchA已經完成等等。謝謝!

+1

不相關,但您可能會考慮使用Alamofire而不是AFNetworking。它是由同一作者撰寫的,但是是一個Swift解決方案。但是你仍然需要做一些事情來處理異步任務,PromiseKit,一些異步操作子類來封裝請求,或者類似的東西。 – Rob

+0

如果你確實留在AFNetworking中,我爲它做了一個'NSOperation'包裝:https://github.com/robertmryan/AFHTTPSessionOperation – Rob

回答

2

您可以使用與DispatchGroup.enter()DispatchGroup.leave()DispatchGroup.modify()混合的串行DispatchQueue,這將確保一次只能運行一個執行塊。

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() 
    } 
} 

或者,如果你被允許使用第三方庫,使用PromiseKit,它使操控,特別是鏈接異步方法比什麼GCD提供了比較容易的方式。有關更多信息,請參閱official GitHub頁面。 你可以用與在承諾完成處理異步方法,並把它們結合在一起是這樣的:

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

}.catch{ error in 
    //handle error 
} 

而且,所有的錯誤都通過你的承諾傳播。

+1

當fetchA/B/C本身是異步的時候,這是行不通的 – dan

+1

包括一個DispatchGroup in該解決方案現在可以正常工作。還提供了PromiseKit作爲替代方案。 –

+0

承諾是要走的路! –