Combine — collect()

`collect()` is a powerful operator that enables us to receive all at once the outputs from a publisher.

It collects all received elements, and emits a single array of the collection when the upstream publisher finishes.

[0, 1, 2, 3].publisher
.sink { (output) in
print(output)
}.store(in: &subscriptions)

The publisher will emit the values as they come — e.g starting with 0 and ending with 3 —

// 0
// 1
// 2
// 3

Using `collect()`, the publisher will hold the values and emit all of them once a `finished` event is sent — e.g when the last element of the sequence is emitted —

[0, 1, 2, 3].publisher
.collect()
.sink { (output) in
print(output)
}.store(in: &subscriptions
// [0, 1, 2, 3]

The nice thing about `collect()` is that we can combine it with the `MergeMany` built-in publisher to handle efficiently multiple asynchronous requests.

`MergeMany` will create a single publisher from multiple sources and once it finishes, the outputs will be sent to the downstream subscriber all at once.

Let’s create some delay to simulate asynchronous network requests.

let publishers = [0, 1, 2, 3]
.map { n in
Just(n).delay(
for: .seconds(Int.random(in: 2…4)),
scheduler: DispatchQueue.main
)
}
Publishers.MergeMany(publishers)
.collect()
.sink { (output) in
print(output)
}.store(in: &subscriptions)

The `MergeMany` publisher won’t emit any values until all upstream publishers complete their tasks — e.g `Just` will deliver a single output and then finishes —

// [1, 0, 2, 3]

--

--

Jullian Mercier

Senior iOS engineer. jullianmercier.com. @jullian_mercier. Currently looking for new job opportunities.