There was a WWDC movie mentioned, and I believe it's "Combine in Practice" from 2019, start watching around 6:24: https://developer.apple.com/wwdc19/721
Yes, .catch()
terminates the upstream publisher (movie 7:45) and replaces it with a given one in the arguments to .catch
thus usually resulting in .finished
being delivered when using Just()
as the replacement publisher.
If the original publisher should continue to work after a failure, a construct involving .flatMap()
is requried (movie 9:34). The operator resulting in a possible failure needs to be executed within the .flatMap
, and can be processed there if necessary. The trick is to use
.flatMap { data in
return Just(data).decode(...).catch { Just(replacement) }
}
instead of
.catch { return Just(replacement) } // DOES STOP UPSTREAM PUBLISHER
Inside .flatMap
you always replace the publisher and thus do not care if that replacement publisher is terminated by .catch
, since its already a replacement and our original upstream publisher is safe. This example is from the movie.
This is also the answer to your Edit: question, on how to turn a <Output, Error>
into <Output, Never>
, since the .flatMap
does not output any errors, its Never before and after the flatMap. All error-related steps are encapsulated in the flatMap.
(Hint to check for Failure=Never
: if you get Xcode autocompletion for .assign(to:)
then I believe you have a Failure=Never stream, that subscriber is not available otherwise.
And finally the full playground code
PlaygroundSupport.PlaygroundPage.current.needsIndefiniteExecution = true
enum MyError: Error {
case someError
}
let cancellable = Timer.publish(every: 1, on: .main, in: .default)
.autoconnect()
.flatMap({ (input) in
Just(input)
.tryMap({ (input) -> String in
if Bool.random() {
throw MyError.someError
} else {
return "we're in the else case"
}
})
.catch { (error) in
Just("replaced error")
}
})
.sink(receiveCompletion: { (completion) in
print(completion)
PlaygroundSupport.PlaygroundPage.current.finishExecution()
}) { (output) in
print(output)
}
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…