PinkiePie-Z
PinkiePie-Z

Reputation: 553

Chaining Combine.Publisher and calling completion when finished

I'm trying to call several publishers in sequence and call the completionBlock when the last one is finished. All the return type of the publishers is AnyPublisher<Void, Error>. Compared to the solution below, can I do it with .flatMap or some other functions provided in Publishers?

private var firstObserver: AnyCancellable?
private var secondObserver: AnyCancellable?

public func setup() {
    firstObserver = Manager.firstPublisher()
        .sink(receiveCompletion: {_ in}, receiveValue: {[weak self] _ in
            self?.secondObserver = Manager.secondPublisher()
                .sink(receiveCompletion: {_ in}, receiveValue: {[weak self] _ in
                    self?.completionBlock()
                }
        })
}

Upvotes: 0

Views: 1949

Answers (1)

matt
matt

Reputation: 535139

If the publishers depend on each other, you should chain with .flatMap. If not, you could use .append instead. Either way, if all of these publishers are one-shot publishers (they all send a completion after one value), then the chain will be torn down in good order when all have fired.

Example 1:

    Just(1)
        .flatMap { Just(($0,2)) }
        .flatMap { Just(($0.0, $0.1, 3)) }
        .sink(receiveCompletion: {print($0)},
              receiveValue: {print($0)})
        .store(in:&storage)
        // (1,2,3) as a tuple, then finished

Example 2:

    Just(1).append(Just(2).append(Just(3)))
        .sink(receiveCompletion: {print($0)},
              receiveValue: {print($0)})
        .store(in:&storage)
    // 1, then 2, then 3, then finished

Upvotes: 3

Related Questions