介绍一下Swift的异步算法

376 阅读4分钟

作为Swift向安全、简单、高性能的异步编程迈进的一部分,我们很高兴为AsyncSequence 介绍一个新的算法包。它被称为Swift 异步算法,现在可以在 GitHub 上使用。

这个包有三个主要目标:

  • 一流的集成,与async/await
  • 为基于时间的算法提供一个家园
  • 跨平台和开放源代码

动机

AsyncAlgorithms是一个用于处理随时间变化的数值的算法包。这包括那些主要关于时间的算法,如debouncethrottle ,但也包括关于顺序的算法,如combineLatestmerge 。处理多个输入的操作(像zipSequence ),实现起来可能出奇的复杂,有微妙的行为和许多边缘情况需要考虑。一个共享包可以通过广泛的测试和文档来正确处理这些细节,从而使所有Swift应用程序受益。

AsyncAlgorithms的基础已经包含在Swift 5.5的AsyncSequence中。Swift 5.5还带来了使用自然的for/in 循环与await ,以处理AsyncSequenceSequence-等同的API中的值,如mapfilter 。结构化并发允许我们编写中间状态只是一个局部变量的代码,try ,可以直接用于throw 的函数,一般来说,对待异步代码的逻辑与同步代码的逻辑类似。

我们相信一个开源包将为这些API提供一个很好的家。一个软件包可以让开发者灵活地跨平台和操作系统版本进行部署。开发和API设计将在GitHubSwift论坛上进行。

简要浏览

该软件包包括AsyncSequence 熟悉的算法的版本,如:

  • Zip
  • CombineLatest
  • Merge
  • Chain
  • Buffer
  • Debounce
  • Throttle

让我们先来看看zip 。像它的Sequencezip 产生由两个不同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
}

其他算法,如combineLatestmerge 也结合了几个AsyncSequences 的输出。每个算法都对输出的类型和时间提供了不同的控制。


SequenceAsyncSequence 的一个根本区别是引入了时间变量。在对时钟和持续时间进行标准化的基础上,该软件包增加了像debouncethrottle 的算法。它们为常见的操作提供了简单的、开箱即用的解决方案,如丢弃到达速度太快的值:

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是基于PublisherSubscriber 接口,并有操作符在它们之间进行连接。它的设计重点是提供一种方法来声明性地指定这些运算符的链,在数据从一端移动到另一端时进行转换。这需要对中间状态进行不同的思考。有时这会导致调用站点比人们预期的要复杂--特别是在处理单个值、错误或需要共享的数据时。async/await'的结构化并发为我们提供了一种表达这种逻辑的新方法。我们现在可以编写异步代码,这些代码被分割成小块,从上到下读取,而不是作为一系列链式转换。

我们对async/awaitAsyncSequence 为语言带来的可能性感到兴奋。我们相信这个包将是一个很好的地方,可以探索这个空间中更高级别的API的未来发展和演变。

下一步是什么

今天我们发布了Swift异步算法包的原型版本。我们的目的是用一个工作实现来启动这个项目,然后在 Swift 论坛上进行详细的设计讨论。我们欢迎社区参与其中:

  • 早期采用该包并对设计进行反馈
  • 该软件包的实施
  • 测试的实施
  • 为软件包的未来发展提供建议和建议。