作为Swift向安全、简单、高性能的异步编程迈进的一部分,我们很高兴为AsyncSequence 介绍一个新的算法包。它被称为Swift 异步算法,现在可以在 GitHub 上使用。
这个包有三个主要目标:
- 一流的集成,与
async/await - 为基于时间的算法提供一个家园
- 跨平台和开放源代码
动机
AsyncAlgorithms是一个用于处理随时间变化的数值的算法包。这包括那些主要关于时间的算法,如debounce 和throttle ,但也包括关于顺序的算法,如combineLatest 和merge 。处理多个输入的操作(像zip 对Sequence ),实现起来可能出奇的复杂,有微妙的行为和许多边缘情况需要考虑。一个共享包可以通过广泛的测试和文档来正确处理这些细节,从而使所有Swift应用程序受益。
AsyncAlgorithms的基础已经包含在Swift 5.5的AsyncSequence中。Swift 5.5还带来了使用自然的for/in 循环与await ,以处理AsyncSequence 和Sequence-等同的API中的值,如map 和filter 。结构化并发允许我们编写中间状态只是一个局部变量的代码,try ,可以直接用于throw 的函数,一般来说,对待异步代码的逻辑与同步代码的逻辑类似。
我们相信一个开源包将为这些API提供一个很好的家。一个软件包可以让开发者灵活地跨平台和操作系统版本进行部署。开发和API设计将在GitHub和Swift论坛上进行。
简要浏览
该软件包包括AsyncSequence 熟悉的算法的版本,如:
- Zip
- CombineLatest
- Merge
- Chain
- Buffer
- Debounce
- Throttle
让我们先来看看zip 。像它的Sequence ,zip 产生由两个不同AsyncSequence的值组成的图元:
for await (number, letter) in zip(numbers, letters) {
print(number, letter)
}
AsyncSequence 支持 ,这意味着错误处理和使用 一样简单--和其他 Swift 代码一样。rethrows try
do {
for try await (number, letter) in zip(numbers, lettersWithErrors) {
print(number, letter)
}
} catch {
// Handle error
}
其他算法,如combineLatest 和merge 也结合了几个AsyncSequences 的输出。每个算法都对输出的类型和时间提供了不同的控制。
Sequence 和AsyncSequence 的一个根本区别是引入了时间变量。在对时钟和持续时间进行标准化的基础上,该软件包增加了像debounce 和throttle 的算法。它们为常见的操作提供了简单的、开箱即用的解决方案,如丢弃到达速度太快的值:
for await value in input.debounce(for: .seconds(0.5)) {
// Handle input, at most once per 0.5 seconds.
}
在一个有限的异步序列中等待所有值的集合往往是有用的。这个包提供了初始化器,只需一行代码就可以做到这一点:
let result = await Array(input)
async 函数对于将同步的Sequences与AsyncSequence 。这里,我们将它与chain 函数一起使用,为一个文件的内容添加一个序言:
let preamble = [
"// This source file is part of the Swift.org open source project"
"//"
""
].async
let lines = chain(preamble, URL(fileURLWithPath: "/tmp/Sample.swift").lines)
for try await line in lines {
print(line)
}
合并
苹果在iOS 13和macOS 10.15 SDKs中引入了Combine框架。从那时起,我们就有机会了解Combine在现实世界中的使用情况。通过AsyncAlgorithms,我们正在应用这些经验,以及拥抱Swift的新结构化并发功能。
Combine的API是基于Publisher 和Subscriber 接口,并有操作符在它们之间进行连接。它的设计重点是提供一种方法来声明性地指定这些运算符的链,在数据从一端移动到另一端时进行转换。这需要对中间状态进行不同的思考。有时这会导致调用站点比人们预期的要复杂--特别是在处理单个值、错误或需要共享的数据时。async/await'的结构化并发为我们提供了一种表达这种逻辑的新方法。我们现在可以编写异步代码,这些代码被分割成小块,从上到下读取,而不是作为一系列链式转换。
我们对async/await 和AsyncSequence 为语言带来的可能性感到兴奋。我们相信这个包将是一个很好的地方,可以探索这个空间中更高级别的API的未来发展和演变。
下一步是什么
今天我们发布了Swift异步算法包的原型版本。我们的目的是用一个工作实现来启动这个项目,然后在 Swift 论坛上进行详细的设计讨论。我们欢迎社区参与其中:
- 早期采用该包并对设计进行反馈
- 该软件包的实施
- 测试的实施
- 为软件包的未来发展提供建议和建议。