swift - 如何压缩超过 4 个发布者
问题描述
我正在使用 Swift Combine 来处理我的 API 请求。现在我面临一种情况,我想要将超过 4 个并行请求压缩在一起。在我使用 Zip4() 运算符将 4 个请求压缩在一起之前。我可以想象您分多个步骤进行压缩,但我不知道如何为其编写 receiveValue。
这是我当前代码的简化,包含 4 个并行请求:
Publishers.Zip4(request1, request2, request3, request4)
.sink(receiveCompletion: { completion in
// completion code if all 4 requests completed
}, receiveValue: { request1Response, request2Response, request3Response, request4Response in
// do something with request1Response
// do something with request2Response
// do something with request3Response
// do something with request4Response
}
)
.store(in: &state.subscriptions)
解决方案
阻止您压缩任意数量的发布者的是一个非常不幸的事实,即 Apple 选择将 zip 运算符的输出设为tuple。元组非常不灵活,并且它们的能力有限。你不能有一个元组,比如说,十个元素;而且您甚至不能将元素附加到元组,因为这会导致您获得不同的类型。因此,我们需要的是一个新的操作符,它可以做同样的工作,zip
但会产生一些更强大、更灵活的结果,比如数组。
我们可以制作一个!幸运的是,zip
操作符本身有一个transform
参数,可以让我们指定我们想要的输出类型。
好的,为了说明,我将十个出版商压缩在一起。首先,我将创建一个包含 10 个发布者的数组;他们将仅仅是 Just 出版商,但这足以说明这一点,并且为了证明我没有作弊,我将任意延迟他们每个人:
let justs = (1...10).map {
Just($0)
.delay(for: .seconds(Int.random(in:1...3)), scheduler: DispatchQueue.main)
.eraseToAnyPublisher() }
好的,现在我有一系列发布者,我将它们循环压缩在一起:
let result = justs.dropFirst().reduce(into: AnyPublisher(justs[0].map{[$0]})) {
res, just in
res = res.zip(just) {
i1, i2 -> [Int] in
return i1 + [i2]
}.eraseToAnyPublisher()
}
注意运算符后面的尾随闭包zip
!这确保我的输出将是一个Array<Int>
而不是一个元组。与元组不同,我可以创建任意大小的数组,只需每次通过循环添加元素。
好的,result
现在是一个 Zip 发布者,它将十个发布者压缩在一起。为了证明这一点,我只需将订阅者附加到它并打印输出:
result.sink {print($0)}.store(in: &self.storage)
我们运行代码。有一个令人心碎的停顿——没错,因为每个 Just 发布者都有不同的随机延迟,而 zip 的规则是他们都需要在我们得到任何输出之前发布。他们迟早都会这样做,并且输出会出现在控制台中:
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
完全正确的答案!我已经证明我确实将十个出版商压缩在一起,以产生由他们每个人的单一贡献组成的输出。
将任意数量的数据任务发布者(或您正在使用的任何东西)压缩在一起也没有什么不同。
(有关我学习如何序列化任意数量的数据任务发布者的相关问题,请参阅组合框架序列化异步操作。)
推荐阅读
- python - Mac 上的 Python os.cpu_count() 返回错误的内核数
- css - 在 iOS 中的 Safari 上向下滚动时,当在容器上设置高度时,页面很容易横向滚动
- c# - 是否可以使用 2 个单独的密码创建 ASP.NET 用户?
- sql - Create After Trigger 有效,但 Create Before 无效
- javascript - 如何仅为特定元素启用 document.designMode = 'on'
- javascript - React Native web 故事书 react-native-vector-icons 问题图标
- swift - Swift UI 在集合中绑定 TextField
- bash - 当您有 grep.lineNumber=true 时,如何禁用 git grep 中的行号?
- nginx - 代理应该在 Host 标头中传递什么?
- parsing - 如何在 ANTLR 语法中指定行首关键字(这也适用于第一行输入)