In the example below, "2" will never be printed, since the error is a completion event, stopping the publisher from sending any more events. That's very clear to me.
import Combine
enum TestError: Error {
case ohnoes
}
let publisher = PassthroughSubject<Int, Error>()
publisher
.sink(receiveCompletion: { completion in
print(completion)
}) { int in
print(int)
}
publisher.send(1)
publisher.send(completion: .failure(TestError.ohnoes))
publisher.send(2)
Sadly, even replaceError
and catch
won't stop the completion event, so the pipeline will still end.
So my question is, how can I replace the error with a nil
value and prevent the completion event? Basically I want to transform AnyPublisher<Int, Error>
into AnyPublisher<Int?, Never>
, for those cases where I simply don't care about the error at all, and just want to keep receiving future values.
With ReactiveKit I had this extension:
extension Signal {
func errorToOptional() -> Signal<Element?, Never> {
return Signal<Element?, Never> { observer in
self.observe { event in
switch event {
case .next(let element):
observer.receive(element)
case .failed:
observer.receive(nil)
case .completed:
observer.receive(completion: .finished)
}
}
}
}
}
And it worked great. But the Combine types make creating extensions like these very difficult (if not impossible?).
You said
publisher.send(completion: .failure(TestError.ohnoes))
The publisher therefore emits a failure. That is what you told it to do. If a publisher emits a failure, it is dead by definition. That is what failure means in Combine. You cannot do anything downstream of the publisher that will magically change that.
So my question is, how can I replace the error with a nil value and prevent the completion event?
You can prevent the error (failure) from reaching the sink by putting something between the publisher and the sink that catches the error or transforms it into Never. But you cannot prevent the publisher from failing because that is what you just told it to do.
Basically I want to transform AnyPublisher into AnyPublisher, for those cases where I simply don't care about the error at all, and just want to keep receiving future values.
There are not going to be any future values coming from this publisher. It has failed. That is what emitting an error means. And that is what you told the publisher to do.