4

We know Empty Publisher in Combine will trigger a completion event immediately:

Empty<Void,Never>()
    .sink {
        print("completion: \($0)")  // will print!
    } receiveValue: {}

But Empty Publisher that flatMap returned will NOT trigger completion event:

var subs = Set<AnyCancellable>()
let p0 = PassthroughSubject<[Int],Error>()
let p1 = p0
    .flatMap {_ in
        Empty<Void,Never>() // same Empty Publisher
    }.eraseToAnyPublisher()

p1
    .sink {
        print("completion: \($0)")  // but NOT print!
    } receiveValue: {}
    .store(in: &subs)

p0.send([1,2,3])

Why is that??? Am I miss something??? Thanks! ;)

hopy
  • 559
  • 3
  • 18
  • You seem to have misunderstood the semantics of `flatMap`. `p0.flatMap(f)` gives you a publisher that, _for each_ element `x` that `p0` publishes, instead of publishing `x`, it publishes what the publisher `f(x)` would publish. When will `p0.flatMap(f)` complete publishing? Clearly, that doesn't depend on `f(x)` - it depends on `p0`. – Sweeper May 05 '21 at 00:59
  • What exactly are you trying to achieve with your code? Do you want the upstream publisher to stop once some condition is met or something like that? – Sweeper May 05 '21 at 01:00

1 Answers1

5

FlatMap works in the following way: for every upstream value it creates a publisher. The downstream receives all the values emitted by all these FlatMap-created publishers.

It completes when the upstream completes, or errors out if either the upstream errors out, or if any created publishers error out.

So, in your case, for the single upstream value of [1,2,3] you emit an Empty publisher (which completes), but there's no overall completion because PassthroughSubject hasn't completed.

p0.send([1,2,3])
p0.send(completion: .finished)

The above would complete the entire pipeline.

New Dev
  • 48,427
  • 12
  • 87
  • 129