我正在使用Swift合并来处理我的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)
9条答案
按热度按时间wmomyfyw1#
阻止你压缩任意数量的发布者的是一个非常不幸的事实,苹果公司选择把压缩操作符的输出变成一个 * 元组 *。元组是非常不灵活的,而且能力有限。你不可能有一个元组,比如说,10个元素;你甚至不能把一个元素附加到元组上,因为这会导致你得到一个不同的类型。因此,我们需要一个new运算符,它做的工作和
zip
一样,但是发出一些更强大和灵活的结果,比如数组。幸运的是,
zip
操作符本身有一个transform
参数,它允许我们指定想要的输出类型。好的,为了说明,我将压缩 ten publishers。首先,我将创建一个由十个publishers组成的数组;他们将仅仅只是出版商,但这足以表明这一点,并证明我没有作弊,我将附加一个任意的延迟到他们每个人:
好了,现在我有了一个发布者数组,我将把它们压缩在一个循环中:
注意
zip
操作符后面的闭包!这确保了我的输出将是一个Array<Int>
而不是一个元组。与元组不同的是,我可以创建任意大小的数组,每次通过循环时只添加元素。好的,
result
现在是一个Zip发布者,它可以压缩 * 十个发布者 *。为了证明这一点,我将把一个订阅者附加到它并打印输出:我们运行代码时,会有一个令人心跳停止的停顿--这是正确的,因为每个Just发布者都有不同的随机延迟,而zip的规则是,它们 * 都 * 需要在我们得到任何输出之前发布。它们迟早都会这样做,输出会出现在控制台中:
完全正确的答案!我已经证明了我确实把十个出版商压缩在一起,产生了由他们每个人的单一贡献组成的输出。
将任意数量的数据任务发布器(或您正在使用的任何发布器)压缩在一起也没有什么不同。
(For一个相关问题,我在其中学习了如何 * 序列化 * 任意数量的数据任务发布者,请参见Combine framework serialize async operations。)
lbsnaicq2#
你可以这样做:
oyjwcjzk3#
基于Matt's answer:
单元测试可以使用以下内容作为输入:
.receive(on:)
将该事件的发射放在主队列的末尾,以便它将在"second"
之后发射。pod7payv4#
如果你想继续使用
Zip
语义,你可以为此编写一个自定义发布者。基本上,新的Zip5
将是Zip4
和第五个发布者之间的Zip
。以类似的方式,
Zip6
、Zip7
可以写成:Zip6 => Zip(Zip4(a, b, c, d, e), Zip(e, f))
Zip7 => Zip(Zip4(a, b, c, d, e), Zip3(e, f, g))
等等。
缺点是,这需要编写大量代码,如果你最终需要这种
zip
操作,也许这将是一个很好的机会来重新访问你的应用程序的设计,也许你根本不需要这么多的压缩。为了支持上述内容,请看一下
zip6()
声明的样子:有如此多的泛型参数,以及所有泛型参数上的条件约束,会让使用和了解变得更困难。
a14dhokn5#
通过使用transform对我有效
或使用Publishers.Zip4的示例
mbyulnm06#
(1)Predrag's与(2)Matt的答案
(1)我有一个麻烦,记住,如何使用的结果(命名在闭包不是在一些“容易记住”的符号
(2)Matt的解决方案仅限于相同的输出类型,zip没有此限制
我建议用另一种方式
这仍然是远远不够的最佳,但(至少对我来说)更容易使用和压缩出版商的数量几乎是无限的。
从快速语法
这似乎可以通过编译器来解决,也许我们必须要求社区包含一些复合类型的扁平化,以便为我们提供优势。
cclgggtu7#
我认为我需要这样的东西,但根据您的用例,您也可以使用
collect()
来等待所有上游出版商的完成,然后再做其他事情。uhry853o8#
@马特的解决方案是要走的路!
我会使用简化版的reduce部分,基本上是从一个空的元素数组开始,然后在另一个版本的reduce函数中压缩10个justs中的每一个。
因此我不需要
dropFirst()
,在reduce闭包中我可以使用隐式return语句,注意zip
闭包也更短,因为使用了swift语法糖。下面我们来看看更新后的版本:
ryevplcw9#
the article启发了一个解决方案,您可以按以下方式使用它:
第一个