Hi, I'm seeming some odd behaviour with failure handling and the flatMap
operator. It seems that if a Publisher inside a flatMap
fails, this doesn't result in downstream publishers entering a failed state where no more values are propagated. Instead, the downstream publishers will propagate the failure and then continue to propagate values as well.
Here's a quick example:
import Combine
enum IntError: Error {
case badInt
}
let subject = PassthroughSubject<Int, IntError>()
subject
.flatMap { x -> AnyPublisher<Int, IntError> in
if x == 2 {
return Publishers.Fail(error: IntError.badInt).eraseToAnyPublisher()
} else {
return Just(x).setFailureType(to: IntError.self).eraseToAnyPublisher()
}
}
.map { $0 * 2 }
.sink(
receiveCompletion: { completion in
switch completion {
case .failure:
print("Failure")
case .finished:
print("Finished")
}
},
receiveValue: { value in
print("Value: \(value)")
})
subject.send(1)
subject.send(2)
subject.send(3)
This results in:
Value: 2
Failure
Value: 6
Coming from the Rx and ReactiveSwift world, this seems like a bug. The failure should cause the flatMap
to enter a failed state. Or at the very least cause the downstream map
to enter a failed state. Does Combine deliberately behave differently, as if the downstreams are created anew when a flatMap creates a new Publisher, or is this a bug?