文档
Afluent 是一个 Swift 库,介于 swift-async-algorithms 和 Foundation 之间,为 async/await 和 AsyncSequence 添加了响应式操作符。 Afluent 的目标是提供一种响应式友好的操作符风格 API,以增强 Apple 的产品。 因此,Afluent 将添加 Apple 已经构建或正在积极构建的功能。 虽然 async/await 简化了异步代码,但它没有提供 Combine 所具备的用于转换、组合和错误处理的完整操作套件。 Afluent 有意保留尽可能多的 Combine API,以使从 Combine 迁移到 Afluent 更加容易。 因此,在同一个文件中同时导入 Combine 和 Afluent 时,可能会遇到一些小的符号冲突。
map
、flatMap
、catch
、retry
等等async/await
语法无缝协作而构建async/await
测试需求在 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"),
])
虽然 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.
在此示例中
DeferredTask
启动异步任务。map
从 URLSession 数据任务响应中提取数据有效负载。decode
获取该数据并将其解码为 Post 对象数组。retry
将在遇到错误时重试该任务。execute
运行整个链并等待结果。run
运行整个链而不等待结果。有时您需要序列机制,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 的可链接接口减少了样板代码,使复杂操作更加简洁。
内置错误处理:Afluent 的 retry
方法优雅地处理重试,无需手动循环和错误检查。
丰富的操作集:除了重试之外,Afluent 还提供 map
、flatMap
和超过 20 多个操作,丰富了 async/await
的体验。
可读性:Afluent 的流畅设计使代码的意图更加清晰,从而增强了可维护性。
通过使用丰富的操作集增强 async/await
,Afluent 简化并提升了 Swift 中的异步编码体验。
如果您熟悉 Combine 并且希望过渡到 Afluent,本指南将帮助您了解相似之处和不同之处,从而使您的采用过程更加顺畅。 Afluent 有意使用与 Combine 非常相似的 API,从而使过渡更容易。
Publishers
。AsynchonousUnitOfWork
。 这非常适合网络请求或其他“一次性”异步操作,并附带 Combine 附带的所有运算符(包括 share
)。AsyncSequence
,并且只需依赖于 Afluent 运算符,这些运算符扩展了标准库和 Apple 的开源 Swift Async Algorithms 包。 它本身与 Combine 没有 100% 的奇偶校验,但是当与 Apple 的两个库结合使用时,几乎完全提供了与 Combine 相同的运算符。async/await
构建:Afluent 围绕 Swift 的 async/await
和 AsyncSequence
语法设计,使其自然适合新的并发模型。Just
和 Future
:在 Combine 中,您可以使用 Just
获取立即值,使用 Future
获取异步操作。
AsynchronousUnitOfWork
,DeferredTask
将替换 Just
和 Future
。AsyncSequence
,Afluent 提供了一个 Just
序列,而标准库的 AsyncStream
或 AsyncThrowingStream
提供了与 Combine 的 Future
相同的机制。map
、flatMap
、filter
、merge
、zip
等...:
AsynchronousUnitOfWork
,有意义的运算符都直接在 Afluent 中可用。 例如,map
和 flatMap
非常有意义,但 filter
没有意义,因为 AsynchronousUnitOfWork
始终只会发出一个值。AsyncSequence
,这些运算符几乎完全由 Foundation 或 AsyncAlgorithms 提供。catch
和 retry
:Afluent 提供了这些方法,类似于 Combine,用于处理错误和重试操作。
assign
:Afluent 还有一个 assign
运算符,类似于 Combine 的。
sink
和 subscribe
:
AsynchronousUnitOfWork
,subscribe
是 Afluent 提供的方法。 它特意与 sink
略有不同,因为只会发出一个值。 但是,它们具有相同的总体用途。AsyncSequence
,Afluent 提供了一个 sink
方法,其工作方式与 Combine 相同。了解范围:
DeferredTask
并从那里开始。接受差异:Afluent 没有像 Combine 中的发布者那样具有可自定义的 Failure
类型。 每个 AsynchronousUnitOfWork
都可以抛出 CancellationError
,使失败类型始终为 Error
。
使用文档:Afluent 的 文档 是一项宝贵的资源。 在过渡时经常参考它。
加入社区:在 GitHub 上与其他 Afluent 用户互动。 分享经验和解决方案可能是有益的。
请记住,虽然 Afluent 和 Combine 有相似之处,但它们是具有各自优势的不同库。 接受学习曲线,很快您就可以在您的项目中利用 Afluent 的强大功能。
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