2017-08-14 65 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

承诺是要走的路! –