Search code examples
swiftcombinepublisher

Why Empty Publisher not trigger completion event in Combine?


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! ;)


Solution

  • 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.