并行循环的基本思想是使用withTaskGroup,然后为每个异步调用使用addTask。然而,诀窍在于,人们通常希望能够将响应与原始数组中的项目相关联(因为在并发运行时,您无法保证收到响应的顺序)。因此,您可以使用带有结果的字典。例如,如果您的 Friend 对象是 Identifiable,您可以这样做:
func objects(for friends: [Friend]) async -> [Friend.ID: JSObject] {
await withTaskGroup(of: (Friend.ID, JSObject).self) { group in
for friend in friends {
group.addTask { await (friend.id, FriendsPlugin.createFriendResult(friend)) }
}
// build dictionary from array of tuples
var dictionary: [Friend.ID: JSObject] = [:]
while let (index, object) = await group.next() {
dictionary[index] = object
}
// now return array of objects in the order that the friends appeared in the original array
return dictionary
}
}
或者,更简洁地说:
func objects(for friends: [Friend]) async -> [Friend.ID: JSObject] {
await withTaskGroup(of: (Friend.ID, JSObject).self) { group in
for friend in friends {
group.addTask { await (friend.id, FriendsPlugin.createFriendResult(friend)) }
}
return await group.reduce(into: [:]) { $0[$1.0] = $1.1 }
}
}
或者,如果您只是想要一个 [JSObject] 数组:
func objects(for friends: [Friend]) async -> [JSObject] {
await withTaskGroup(of: (Int, JSObject).self) { group in
for (index, friend) in friends.enumerated() {
group.addTask { await (index, FriendsPlugin.createFriendResult(friend)) }
}
// build dictionary from array of tuples
var dictionary: [Int: JSObject] = [:]
while let (index, object) = await group.next() {
dictionary[index] = object
}
// now return array of objects in the order that the friends appeared in the original array
return friends.indices.compactMap { dictionary[$0] }
}
}
或者,再一次,更简洁:
func objects(for friends: [Friend]) async -> [JSObject] {
await withTaskGroup(of: (Int, JSObject).self) { group in
for (index, friend) in friends.enumerated() {
group.addTask { await (index, FriendsPlugin.createFriendResult(friend)) }
}
let dictionary: [Int: JSObject] = await group.reduce(into: [:]) { $0[$1.0] = $1.1 }
return friends.indices.compactMap { dictionary[$0] }
}
}
主题有很多变化,但想法是使用withTaskGroup/addTask 同时运行请求,然后将结果整理成某种结构,您可以通过该结构将响应与原始数组中的项目相关联。