La documentación de Swift Concurrency proporciona el siguiente ejemplo de cómo esperar varias funciones asíncronas en paralelo.
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]¿Hay alguna forma de esperar un número arbitrario de funciones asíncronas en paralelo? Probé el enfoque que se muestra en el código a continuación, pero no pude encontrar una manera de hacerlo funcionar.
var photoPromises: [PhotoPromise] = [] for name in photoNames { photoPromises.append(downloadPhoto(named: name)) } let photos = await photoPromisesSí, tienes la idea correcta. Encontré una pregunta similar aquí:
Intente usar una declaración when en su lugar para esperar las promesas cumplidas:
when(fulfilled: promiseArray).then { results in // Do something }.catch { error in // Handle error }Aquí está la pregunta original, pero el enlace al que se hace referencia allí está roto.
Swift & PromiseKit: resolución de TODAS las promesas de un bucle
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) } }Mapa genérico/versión reducida
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) } }