swift-async-operations
一个扩展异步操作能力的库。
Swift 并发是一个强大的语言特性,但是没有用于 Swift 并发操作数组的 API。开发者需要编写冗余代码。
var results: [Int] = [] // ☹️ var is required.
for await element in [0, 1, 2, 3, 4] {
let newElement = try await twice(element)
result.append(newElement)
}
print(results) // [0, 2, 4, 6, 8]
在需要循环并发执行的情况下,开发者需要编写更多冗余代码。
// ☹️ Long redundant code
let array = [0, 1, 2, 3, 4]
let results = try await withThrowingTaskGroup(of: (Int, Int).self) { group in
for (index, number) in array.enumerated() {
group.addTask {
(index, try await twice(number))
}
}
var results: [Int: Int] = [:]
for try await (index, result) in group {
results[index] = result
}
// ☹️ Need to take the order into account.
return results.sorted(by: { $0.key < $1.key }).map(\.value)
}
print(results) // [0, 2, 4, 6, 8]
这个库提供了异步函数作为 Sequence
的扩展,例如 asyncMap
。
let converted = try await [0, 1, 2, 3, 4].asyncMap { number in
try await twice(number)
}
print(converted) // [0, 2, 4, 6, 8]
默认情况下,闭包顺序执行。通过指定最大任务数,闭包也可以并发执行。
let converted = try await [0, 1, 2, 3, 4].asyncMap(numberOfConcurrentTasks: 8) { number in
try await twice(number)
}
print(converted) // [0, 2, 4, 6, 8]
这个库提供了两个功能。
Sequence
的异步函数。这个库提供了异步操作,例如 asyncForEach
和 asyncMap
。
try await [1, 2, 3].asyncForEach { number in
print("Start: \(number)")
try await doSomething(number)
print("End: \(number)")
}
默认情况下,闭包顺序执行。
Start: 1
End: 1
Start: 2
End: 2
Start: 3
End: 3
作为高级用法,可以指定 numberOfConcurrentTasks
,如果该值大于等于 2,闭包可以并行运行。
try await [1, 2, 3].asyncForEach(numberOfConcurrentTasks: 3) { number in
print("Start: \(number)")
try await doSomething(number)
print("End: \(number)")
}
Start: 2
End: 2
Start: 1
Start: 3
End: 3
End: 1
扩展函数即使对于像 map
函数这样对顺序敏感的函数也执行并行操作,在转换数组的同时保留原始顺序。
let result = try await [1, 2, 3].asyncMap(numberOfConcurrentTasks: 3) { number in
print("Start: \(number)")
let result = try await twice(number)
print("End: \(number)")
return result
}
print(result)
Start: 1
Start: 3
End: 3
End: 1
Start: 2
End: 2
[2, 4, 6]
这个库提供了
原始的实用函数 withTaskGroup
和 withThrowingTaskGroup
不保证 for await
的顺序。
let results = await withTaskGroup(of: Int.self) { group in
(0..<5).forEach { number in
group.addTask {
await Task.yield()
return number * 2
}
}
var results: [Int] = []
for await number in group {
results.append(number)
}
return results
}
print(results) // ☹️ [0, 4, 2, 6, 10, 8]
然而,在某些情况下,例如将数组转换为新数组时,需要有序的 for await
。
withOrderedTaskGroup 和 withThrowingOrderedTaskGroup 满足这些需求。
let results = await withOrderedTaskGroup(of: Int.self) { group in
(0..<5).forEach { number in
group.addTask {
await Task.yield()
return number * 2
}
}
var results: [Int] = []
for await number in group {
results.append(number)
}
return results
}
print(results) // 😁 [0, 2, 4, 6, 8, 10]
它们也被用于 Sequence
的异步函数。
Swift 5.10 或更高版本。
你可以通过 Swift Package Manager 安装这个库。
dependencies: [
.package(url: "https://github.com/mtj0928/swift-async-operations", from: "0.1.0")
]
请查看 DocC 文档页面