如何在循环中处理异步函数?

时间:2018-01-10 04:04:26

标签: swift

我循环遍历表的行,对于每个行我都在做几个异步调用,比如从API获取数据,复制文件,运行shell脚本......如何等待结果直到下一个。

我也是Swift的新手,不知道这是否是处理一组异步任务的最佳方法。在这种情况下我应该使用并发吗?

tableView.selectedRowIndexes.forEach { row in
     myData.fetch(url: urlList[row]) { res in
        self.anotherAsyncCall(res) { data in
            //continue to deal with next row now
        }
    }
}

2 个答案:

答案 0 :(得分:1)

如果您真的想按顺序执行此操作,最简单的方法是递归执行您的任务,实际调用前一个任务的完成处理程序中的下一个任务:

processNext(in: tableView.selectedRowIndexes) {
    // do something when they're all done
}

其中:

func processNext(in rows: [Int], completion: @escaping () -> Void) {
    guard let row = rows.first else {
        completion()
        return
    }

    myData.fetch(url: urlList[row]) { res in
        self.anotherAsyncCall(res) { data in
            //continue to deal with next row now

            self.processNext(in: Array(rows.dropFirst()), completion: completion)
        }
    }
}

但我同意GoodSp33d的另一种方法是将这个异步过程包装在一个自定义的异步Operation子类中。

但这引出了为什么要按顺序执行这些操作的问题。由于每个请求的固有网络延迟,您将支付显着的性能损失。因此,另一种方法是让它们同时运行,并使用调度组来了解它们何时完成:

let group = DispatchGroup()

tableView.selectedRowIndexes.forEach { row in
    group.enter()
    myData.fetch(url: urlList[row]) { res in
        self.anotherAsyncCall(res) { data in
            //continue to deal with next row now
            group.leave()
        }
    }
}

group.notify(queue: .main) {
    // do something when they're all done
}

您是否可以同时(或在何种程度上)运行这些是您在各种异步方法中所做的功能。但我建议你同时努力使这项工作同时进行,因为性能可能要好得多。

答案 1 :(得分:0)

如果您使用的是某个promise库,只需使用all函数。

Here是关于promise.all()

的文档

PromiseKit使用when代替,  您可以阅读faqtutorial about when了解更多信息。

如果你想在没有任何promise库的情况下这样做,这里是伪代码:

var results = []
rows.forEach {row in
    fetch(row) {res in
        results.push(res)
        if(results.length == rows.length) {
            // do something using the results here
        }
    }
}