https://kotlinlang.org logo
#coroutines
Title
# coroutines
m

Marcelo Hernandez

07/08/2019, 5:16 PM
Been converting Rx
Singles
,
Maybes
, and
Completables
to
suspend
functions. I feel that with Rx, error handling is pretty much
try/catch(Throwable)
behind the scenes. So when switching over to coroutines, one might "naively" start using
runCatching { ... }.onSuccess { ... }.onFailure { ... }
or basic
try/catch(Throwable)
. The issue with this is that a
CancellationException
will also be caught when attempting to cancel a coroutine. Does this mean that before refactoring to
suspend
functions, one should begin defining custom, domain-specific Exceptions or leverage some sort of
Result
type in order to avoid
try/catch(Throwable)
?
l

louiscad

07/08/2019, 6:33 PM
There are multiple solutions to this problem. One is to have an empty
catch(ignored: CancellationException)
first, or from which you rethrow (important if there's only custom suspending functions that don't check for cancellation). Another is to catch only the expected exceptions (might be risky if you don't know what can be thrown). You can also check
e is CancellationException
and rethrow it.
m

Marcelo Hernandez

07/08/2019, 6:46 PM
Thank you for your reply!
If I understand correctly, if I were to try and port over existing non-Observable Rx code, with minimal changes, it would go from
Copy code
doRxAsyncWork()
    .subscribeOn(...)
    .observeOn(...)
    .subscribe(
        { ... },
        { error -> // perform error handling }
    )
to
Copy code
try {
    doSuspendingWork()
} catch (ex: CancellationException) {
    throw ex
} catch (ex: Throwable) {
    // perform error handling
}
👌 1
Thanks again! IMO, this does not look as nice as Rx. It does become a harder sell for people who are perfectly happy with RxJava.
One can probably define their own custom
runCatching
utility that catches and re-throws the
CancellationException
.
s

streetsofboston

07/08/2019, 7:30 PM
Yup, I found the same issue. It seems Kotlin here is almost forcing you to never catch exceptions with a broad/wide net. It is indeed better to catch specific exceptions instead of
Exception
, or
Throwable
, etc. In this case it is somewhat forced on you to catch specific ones only
m

Marcelo Hernandez

07/08/2019, 7:37 PM
In general, it has always been good practice to catch specific exceptions. Unfortunately, Rx made it way to easy to overlook this. The issue now is trying to refactor existing non-
Observable
Rx code to
suspend
functions with minimal effort.
p

Paul Woitaschek

07/08/2019, 8:08 PM
Or you don't go the minimal efford way and find erros in your code 😉
☝️ 1
m

Marcelo Hernandez

07/14/2019, 8:16 PM
It seems
Flows
will be getting a
catch
operator that properly handles
CancellationExceptions
. “Exceptions in Kotlin Flows” by Roman Elizarov https://link.medium.com/AenSuqlckY
@elizarov any chance we'll be getting a
runCatching
variant for non-
Flow
suspend
code that also takes
CancellationExceptions
into account?
s

Stephane Maldini

07/15/2019, 10:07 PM
I think you mischaracterized “error handling” as transparent in rx. There are explicit operators to force you to address them because they might happen asynchronously and they don’t suspend/resume to rethrow in the current thread. You actually can’t not deal with errors
i expect Flow to catch up and have a similar operator vocabulary soon enough
4 Views