GitHub Workflow Status (with event) GitHub swift-version xcode-version

Afluent

AfluentLogo

文档

Afluent 是一个 Swift 库,介于 swift-async-algorithms 和 Foundation 之间,为 async/await 和 AsyncSequence 添加了响应式操作符。 Afluent 的目标是提供一种响应式友好的操作符风格 API,以增强 Apple 的产品。 因此,Afluent 将添加 Apple 已经构建或正在积极构建的功能。 虽然 async/await 简化了异步代码,但它没有提供 Combine 所具备的用于转换、组合和错误处理的完整操作套件。 Afluent 有意保留尽可能多的 Combine API,以使从 Combine 迁移到 Afluent 更加容易。 因此,在同一个文件中同时导入 Combine 和 Afluent 时,可能会遇到一些小的符号冲突。

特性

安装

Swift 包管理器

Package.swift 中将 Afluent 包添加到你的目标依赖项中

dependencies: [
    .package(url: "https://github.com/Tyler-Keith-Thompson/Afluent.git", from: "1.0.0")
]

然后,将 Afluent 目标作为依赖项添加到你的包目标中

.target(name: "MyLib",
        dependencies: [
            .product(name: "Afluent", package: "Afluent"),
        ])

对于希望使用 Afluent 测试实用程序的测试目标,将 AfluentTesting 目标添加为依赖项

.testTarget(name: "MyLibTests",
            dependencies: [
                .product(name: "AfluentTesting", package: "Afluent"),
            ])

用法

AsynchronousUnitOfWork

虽然 Combine 始终处理序列,但 async/await 提供任务。 任务与序列的不同之处在于,它们最终只会发出一个值,而序列最终可能会发出零个或多个值。 这意味着,您可以对单一元素的序列使用任务,而无需采用 Combine 的方法,从而确保更可靠的执行。 当处理网络请求时,这非常符合人体工程学,请查看以下示例

struct Post: Codable {
    let userId: UInt
    let id: UInt
    let title: String
    let body: String
}

let posts = try await DeferredTask {
    try await URLSession.shared.data(from: URL(string: "https://jsonplaceholder.typicode.com/posts")!)
}
.map(\.0) // Extract the data from the URLSession response
.decode(type: [Post].self, decoder: JSONDecoder()) // Decode the JSON into an array of `Post` objects
.retry() // Automatically retry the request if it fails
.execute() // Execute the deferred task and await the result.
//.run() // Run could've also been used to execute the task without awaiting the result.

在此示例中

AsyncSequence

有时您需要序列机制,Afluent 可以提供帮助! 这是相同的示例,但已转换为具有所有相同运算符的 AsyncSequence。

let posts = try await DeferredTask {
    try await URLSession.shared.data(from: URL(string: "https://jsonplaceholder.typicode.com/posts")!)
}
.toAsyncSequence() // Convert this to an AsyncSequence, thus enabling Swift Async Algorithms and standard library methods
.map(\.0) // Extract the data from the URLSession response
.decode(type: [Post].self, decoder: JSONDecoder()) // Decode the JSON into an array of `Post` objects
.retry() // Automatically retry the request if it fails
.first() // Get the first result from the sequence

为什么 Afluent 比仅使用 async/await 更好

通过使用丰富的操作集增强 async/await,Afluent 简化并提升了 Swift 中的异步编码体验。

采用 Afluent:Combine 用户的指南

如果您熟悉 Combine 并且希望过渡到 Afluent,本指南将帮助您了解相似之处和不同之处,从而使您的采用过程更加顺畅。 Afluent 有意使用与 Combine 非常相似的 API,从而使过渡更容易。

主要区别

  1. 异步工作单元与发布者与 AsyncSequence:
  1. 专为 async/await 构建:Afluent 围绕 Swift 的 async/awaitAsyncSequence 语法设计,使其自然适合新的并发模型。

将 Combine 映射到 Afluent

过渡提示

  1. 了解范围:

    • 如果您最终只发出一个值,则 Afluent 可以完全替换 Combine。 您可能会使用 DeferredTask 并从那里开始。
    • 如果您随时间推移发出多个值,您可能需要结合使用 Afluent、Foundation 和 AsyncAlgorithms 来补充 Combine。 使用所有这 3 个,您可以获得 Combine 提供的大部分行为。
  2. 接受差异:Afluent 没有像 Combine 中的发布者那样具有可自定义的 Failure 类型。 每个 AsynchronousUnitOfWork 都可以抛出 CancellationError,使失败类型始终为 Error

  3. 使用文档:Afluent 的 文档 是一项宝贵的资源。 在过渡时经常参考它。

  4. 加入社区:在 GitHub 上与其他 Afluent 用户互动。 分享经验和解决方案可能是有益的。

请记住,虽然 Afluent 和 Combine 有相似之处,但它们是具有各自优势的不同库。 接受学习曲线,很快您就可以在您的项目中利用 Afluent 的强大功能。

常见问题解答 (FAQ)

1. 如何为 Afluent 做出贡献或报告问题?
Afluent 托管在 GitHub 上。 您可以 fork 存储库,进行更改并提交 pull 请求。 要报告问题,请在 GitHub 存储库上打开一个新问题,其中包含详细说明。

2. 为什么序列没有 share 运算符?
Afluent 努力不干扰 Apple 正在进行的工作。 社区对多播或共享功能的需求一直很强烈,并且 swift-async-algorithms 团队正在开发一个广播运算符来提供帮助。 同样值得注意的是,解决这个问题并非易事,例如计时操作。 因此,Afluent 团队更愿意将这种复杂性留给 Apple 管理。

3. 如果你不构建 share,为什么你要构建 Deferred
值得注意的是,异步算法团队引入了一个 deferred 全局函数,其操作方式与 Afluent 的 Deferred 序列类似。 Afluent 实现此功能的原因是实现的便利性以及更迫切的需求。 在撰写本文时,Async Algorithms 直到 v1.1 才会发布 deferred,而 Afluent 可以轻松填补这一空白,直到这种情况发生。

4. 为什么是 Afluent 而不是 Affluent? Async/Await + Fluent == Afluent