Dmytro Serdiuk
01/11/2024, 10:32 PMAll exception-handling Flow operators follow the principle of exception suppression:
If the upstream flow throws an exception during its completion when the downstream exception has been thrown, the downstream exception becomes superseded and suppressed by the upstream exception, being a semantic equivalent of throwing from finally block. However, this doesn't affect the operation of the exception-handling operators, which consider the downstream exception to be the root cause and behave as if the upstream didn't throw anything.
If possible with example. Thank you!Sam
01/12/2024, 4:54 PMcatch
operators that would normally intercept errors. You can think of it as being because the exception is "too late" to be caught. Since it's in a finally
or onCompletion
block triggered after the flow's completion, it's being thrown after the catch operators in its path would normally have been triggered. Here's some example code.
suspend fun main() {
flow {
try {
emit("Hello!")
} finally {
error("upstream")
}
}.catch {
println("This never happens, even though the upstream threw an error")
}.collect {
error("downstream")
}
}
When you run the program, you'll see that it fails with the "upstream" exception. This corresponds to the first part of the docs:
If the upstream flow throws an exception during its completion when the downstream exception has been thrown, the downstream exception becomes superseded and suppressed by the upstream exception.However, the
catch
section is not executed. We never see the "This never happens" line of output from the example code, even though the exception was thrown from a part of the flow that is upstream of the catch operator. This is because of the second point in the docs:
However, this doesn't affect the operation of the exception-handling operators, which consider the downstream exception to be the root cause.
Dmytro Serdiuk
01/13/2024, 4:59 PM