如何并行等待任意数量的异步函数


Swift Concurrency文档提供了以下如何并行等待多个异步函数的示例。
async let firstPhoto = downloadPhoto(named: photoNames[0])
async let secondPhoto = downloadPhoto(named: photoNames[1])
async let thirdPhoto = downloadPhoto(named: photoNames[2])
let photos = await [firstPhoto, secondPhoto, thirdPhoto]

有没有一种方法可以并行等待任意数量的异步函数?我尝试了下面代码中显示的方法,但找不到使其工作的方法。

var photoPromises: [PhotoPromise] = []
for name in photoNames {
photoPromises.append(downloadPhoto(named: name))
}
let photos = await photoPromises
import UIKit
import XCTest
struct Downloader
{
static func download(photoURLs: [URL]) async throws -> [UIImage] {
try await withThrowingTaskGroup(of: UIImage.self) { group in
var collected = [UIImage]()
for url in photoURLs {
group.addTask {
let (data, _) = try await URLSession.shared.data(from: url)
return UIImage(data: data)!
}
}
for try await value in group {
collected.append(value)
}
return collected
}
}
}
final class PhotosTests: XCTestCase
{
func testDownloader() async throws {
let images = try await Downloader.download(photoURLs: [
URL(string: "https://placekitten.com/200/300")!,
URL(string: "https://placekitten.com/g/200/300")!
])
XCTAssertNotNil(images[0])
XCTAssertNotNil(images[1])
XCTAssertEqual(images.count, 2)
}
}

通用地图/缩小版

import UIKit
import XCTest
struct MapReduce
{
static func mapReduce<T,U>(inputs: [T], process: @escaping (T) async throws -> U ) async throws -> [U] {
try await withThrowingTaskGroup(of: U.self) { group in
// map
for input in inputs {
group.addTask {
try await process(input)
}
}
// reduce
var collected = [U]()
for try await value in group {
collected.append(value)
}
return collected
}
}
}
final class PhotosTests: XCTestCase
{
func testDownloader() async throws {
let input = [
URL(string: "https://placekitten.com/200/300")!,
URL(string: "https://placekitten.com/g/200/300")!
]
let download: (URL) async throws -> UIImage = { url in
let (data, _) = try await URLSession.shared.data(from: url)
return UIImage(data: data)!
}
let images = try await MapReduce.mapReduce(inputs: input, process: download)
XCTAssertNotNil(images[0])
XCTAssertNotNil(images[1])
XCTAssertEqual(images.count, 2)
}
}

是的,你的想法是对的。我在这里发现了一个类似的问题:

尝试使用when语句来等待兑现的承诺:


when(fulfilled: promiseArray).then { results in
// Do something
}.catch { error in
// Handle error
}

这是最初的问题,但其中引用的链接已断开。

Swift&PromiseKit:从循环解析所有承诺

最新更新