如何压缩4个以上的发布者 [英] How to zip more than 4 publishers

查看:47
本文介绍了如何压缩4个以上的发布者的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在对我的API请求使用Swift Combine.现在,我面临一种情况,我想将4个以上的并行请求压缩在一起.在我有4个使用Zip4()运算符压缩在一起的请求之前.我可以想象您要分多个步骤进行压缩,但是我不知道如何为它编写receiveValue.

I'm using Swift Combine for my API requests. Now I'm facing a situation where I want to have more than 4 parallel requests that I want to zip together. Before I had exactly 4 requests that I zipped together using Zip4() operator. I can imagine that you do the zipping in multiple steps but I don't know how to write the receiveValue for it.

这是我当前代码的简化,其中包含4个并行请求:

Here's a simplification of my current code with 4 parallel requests:

    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)

推荐答案

不幸的是,苹果选择将zip运算符的输出作为元组.元组非常不灵活,并且功能有限.您不能有一个由10个元素组成的元组;而且您甚至无法将元素附加到元组,因为这会导致您获得其他类型.因此,我们需要一个新的运算符,该运算符的作用与 zip 相同,但会发出一些更强大,更灵活的结果,例如数组.

The thing that stops you from zipping an arbitrary number of publishers is the very unfortunate fact that Apple has elected to make the output of the zip operators be a tuple. Tuples are extremely inflexible and limited in their power. You can’t have a tuple of, say, ten elements; and you can’t even append an element to a tuple, because that causes you to get a different type. What we need, therefore, is a new operator that does the same job as zip but emits some more powerful and flexible result, such as an array.

我们可以做一个!幸运的是, zip 运算符本身具有一个 transform 参数,该参数使我们可以指定所需的输出类型.

And we can make one! Luckily, the zip operator itself has a transform parameter that lets us specify what sort of output we want.

好的,为了说明一下,我将把十个发布者压缩在一起.首先,我将组成十个发布者;他们将仅仅是Just Publishers,但这足以说明问题,并证明我没有作弊,我将对他们每个人施加任意延迟:

Okay, so, to illustrate, I'll zip ten publishers together. First, I'll make an array of ten publishers; they will be mere Just publishers, but that's sufficient to make the point, and to prove that I'm not cheating I'll attach an arbitrary delay to each of them:

let justs = (1...10).map {
    Just($0)
        .delay(for: .seconds(Int.random(in:1...3)), scheduler: DispatchQueue.main)
        .eraseToAnyPublisher() }

好的,现在我有了一系列的发布者,我将它们压缩成一个循环:

Okay, now I've got an array of publishers, and I'll zip them together in a loop:

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> 而不是元组.与元组不同,我可以创建任何大小的数组,每次循环都添加元素.

Note the trailing closure after the zip operator! This ensures that my output will be an Array<Int> instead of a tuple. Unlike a tuple, I'm allowed to make an array of any size, just adding elements each time thru the loop.

好的,所以 result 现在是一个Zip发布者,可以将十个发布者压缩在一起.为了证明这一点,我将为其附加一个订户并打印输出:

Okay, so result is now a Zip publisher that zips together ten publishers. To prove it, I'll just attach a subscriber to it and print the output:

result.sink {print($0)}.store(in: &self.storage)

我们运行代码.有一个令人心碎的暂停-正确,因为每个Just发行商都有不同的随机延迟,并且zip规则是他们 all 都需要在我们获得任何输出之前进行发行.他们都会迟早都这样做,并且输出将显示在控制台中:

We run the code. There is a heart-stopping pause — rightly, because each of those Just publishers has a different random delay, and the rule of zip is that they all need to publish before we get any output. They all do, sooner or later, and the output appears in the console:

[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

完全正确的答案!我证明我实际上确实将十个发布者压缩在一起,以产生由每个发布者的一个贡献组成的输出.

Exactly the right answer! I've proved that I did in fact zip ten publishers together to produce output consisting of a single contribution from each of them.

将任意数量的数据任务发布者(或您正在使用的任何东西)压缩在一起并没有什么不同.

Zipping together an arbitrary number of data task publishers (or whatever you're using) is no different.

(关于一个相关问题,我将学习如何序列化任意数量的数据任务发布者,请参见

(For a related question, where I learn how to serialize an arbitrary number of data task publishers, see Combine framework serialize async operations.)

这篇关于如何压缩4个以上的发布者的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆