[英]Swift Async let with loop
我想並行獲取數據。 我找到了一個並行調用 API 的例子,但我想用循環存儲async let variables
。
異步讓示例。 但是,此示例不使用循環。
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]
show(photos)
我想做類似以下的事情。
let items = photoNames.map({ photo in
async let item = downloadPhoto(named: photo)
return item
})
let photos = await items
show(photos)
let photos = await photoNames.map(downloadPhoto)
public extension Sequence {
func map<Transformed>(
priority: TaskPriority? = nil,
_ transform: @escaping (Element) async throws -> Transformed
) async rethrows -> [Transformed] {
try await withThrowingTaskGroup(of: Transformed.self) { group in
for element in self {
group.addTask(priority: priority) {
try await transform(element)
}
}
return try await .init(group)
}
}
}
public extension Array {
init<AsyncSequence: _Concurrency.AsyncSequence>(_ asyncSequence: AsyncSequence) async rethrows
where AsyncSequence.Element == Element {
self = try await asyncSequence.reduce(into: []) { $0.append($1) }
}
}
CollectionConcurrencyKit對此提供了一個變體。
如果結果的順序在這里無關緊要,請改用TaskGroup
。
您可以使用任務組。 請參閱The Swift Programming Language: Concurrency 的Tasks and Task Groups部分(這似乎是您獲得示例的地方)。
可以使用withTaskGroup(of:returning:body:)
創建一個任務組來並行運行任務,但最后將所有結果整理在一起。
例如,這是一個創建子任務的示例,該任務返回“名稱”和“圖像”的元組,並且
func downloadImages(with names: [String]) async -> [String: UIImage] {
await withTaskGroup(
of: (String, UIImage).self,
returning: [String: UIImage].self
) { [self] group in
for name in names {
group.addTask { await (name, downloadPhoto(named: name)) }
}
var images: [String: UIImage] = [:]
for await result in group {
images[result.0] = result.1
}
return images
}
}
或者,更簡潔地說:
func downloadImages(with names: [String]) async -> [String: UIImage] {
await withTaskGroup(
of: (String, UIImage).self,
returning: [String: UIImage].self
) { [self] group in
for name in names {
group.addTask { await (name, downloadPhoto(named: name)) }
}
return await group.reduce(into: [:]) { $0[$1.0] = $1.1 }
}
}
它們並行運行:
但是您可以從結果字典中提取它們:
let stoodges = ["mo", "larry", "curly"]
let images = await downloadImages(with: stoodges)
imageView1.image = images["mo"]
imageView2.image = images["larry"]
imageView3.image = images["curly"]
對於遍歷數組並並行響應,您不使用async let
。 你想象中的代碼...
let items = photoNames.map({ photo in
async let item = downloadPhoto(named: photo)
return item
})
let photos = await items
show(photos)
...只需轉換為使用任務組(直接在瀏覽器中輸入,因此准備根據需要進行補償;另請注意,您提供的信息不足,因為我不知道您從downloadPhoto
返回的是什么類型,所以我必須振作起來):
var result = [YourPhotoType]()
await withTaskGroup(of:YourPhotoType.self) { group in
photoNames.forEach { name in
group.addTask {
async downloadPhoto(named: name)
}
}
for await photo in group {
result.append(photo)
}
}
有關更多信息,請參閱我的教程https://www.biteinteractive.com/swift-5-5-asynchronous-looping-with-async-await/ (特別是關於您現在丟失原始數組順序的問題) )。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.