kotlinx.coroutines: Help newbies to handle exceptions in coroutines
I can’t figure how to catch the exceptions thrown from a launch block. I don’t understand how to use the CoroutineExceptionHandler. I think that the Try pattern is quite heavy (https://github.com/Kotlin/kotlinx.coroutines/blob/master/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/Try.kt). The CompletableFuture wrapper works as expected (simply), but it requires the jdk8 lib.
Thanks for this masterpiece !
import kotlinx.coroutines.experimental.delay
import kotlinx.coroutines.experimental.future.await
import kotlinx.coroutines.experimental.future.future
import kotlinx.coroutines.experimental.launch
import kotlinx.coroutines.experimental.runBlocking
import org.junit.Ignore
import org.junit.Test
import java.util.concurrent.atomic.AtomicBoolean
class CoroutinesTest {
class TestException: Exception("test exception")
@Test
@Ignore("not that way...")
fun testExceptionOnLaunch_tryCatch() {
runBlocking {
val caught = AtomicBoolean(false)
val job = launch(context) {
delay(10)
throw TestException()
}
try {
job.join()
} catch (e: TestException) {
caught.set(true)
} finally {
assert(caught.get())
}
}
}
@Test
@Ignore("not that way...")
fun testExceptionOnLaunch_getCompletionException() {
runBlocking {
val job = launch(context) {
delay(10)
throw TestException()
}
try {
job.join()
} finally {
val exc = job.getCompletionException()
assert(exc is TestException)
}
}
}
@Test
fun testExceptionOnFuture() {
System.setProperty("kotlinx.coroutines.debug", "off")
runBlocking {
val caught = AtomicBoolean(false)
val job = future(context) {
delay(10)
throw TestException()
}
try {
job.await()
} catch (e: TestException) {
caught.set(true)
} finally {
assert(caught.get())
}
}
}
}
About this issue
- Original URL
- State: closed
- Created 7 years ago
- Reactions: 7
- Comments: 25 (8 by maintainers)
Honestly Kotlin seems to be a crap in the long term, more like wheel reinventing. Didn’t use beautiful features of C#, Java, just created a new way of doing everything things.
So kotlin is trying to say that, i cant handle error like the popular Promise way? example
Defered.onError(//pass a lambda here),The learning curve is fucking high, Docs didnt explain things well. all i gain is
I really want to help in the Docs, fuck coroutines. (Not really happy with this kotlin, I feeling threatened my Java was getting obsolete and wasted my time learning kotlin)
I still Love The Challenge Kotlin is giving me though, good work guys 😃
You can switch to
asyncinstead oflaunchand useawaitinstead ofjoin. This way exceptions will percolated to the functions thatawait. I’ll keep this issue open, because there is definitely a need for a more detailed explanation in docs.Hi @Zedonboy
Have fun
@pdegand Just replace
launchwithasyncin the above above code and you’ll get what you are looking for:asyncreturns.it.joinas you do now to wait for all of them and you can also save the resulting list ofDeferredobjects to analyze which ones had failed and which did not later on. SeeDeferreddocumentation for more details: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-deferred/index.htmlThe recommended way, for now, is to use
try { ... } catch { ... }in the code of the coroutine. We might consider adding helper function to restart coroutine on exception in the future. Please, create a separate issue if you have any specific ideas on how this kind of API might look like.Thanks @fvasco , sometimes it takes time to learn a new language and master. My comfort zone was Javascript. Now working on a production grade Android Software with Kotlin. (Finally am falling in love)
Keep up the good work guys.
can you give an example of this extension function in action?
Feel free to lift Arrow’s extension functions for this: https://github.com/arrow-kt/arrow/blob/master/modules/effects/arrow-effects-kotlinx-coroutines/src/main/kotlin/arrow/effects/DeferredK.kt
Replace
Trywithtry/catchand a function catch block and it should work the same.@elizarov I’ve investigated some more and there are some interesting things happening. For testing I’ve set up the following Activity in an newly created project:
On a Sony Xperia Z3 API 23 everything works as intended. The app is crashing and the stacktrace is printed to Logcat.
But run the same code on a Samsung S8 API 26 and the app is crashing but there is no stacktrace in Logcat. This is 100% reproducable but I don’t know where’s the root error causing this. Maybe we should create a seperate issue for that?
To answer your question what I want to archieve: If there is an exception in
launch, I want the app to crash and the stacktrace printed into Logcat, so that the other developers and I know what we’ve done wrong during development (the printing is even more important than the crashing).For now, I’m using your approach which works on API 26, too:
Or are there any drawbacks I’m not aware of with this solution?
PS: I’m a big fan of your work and I want to use them as an integral part of our application, but I also have to convince my superiors that they work better than conventional handlers and threads 🤖
EDIT: You must launch another coroutine with context
kotlinx.coroutines.experimental.android.UIto actually throw the exception on the main thread and get a crash@MariusBoepple Uncaught exceptions in
launchare designed to crash your app. If you want to handle them different, you should either wrap your code withtry { ... } catch { ... }or create your own context withCoroutineExceptionHandlerlike this:I’m curious at what exactly you are trying to achieve? What do you want to do on exception?
@elizarov the following code does just crash without logging anything (
NetworkOnMainThreadException). We stumble over the exception handling in the coroutines all the time and it would be nice to have a more convenient solution. Or am I doing something wrong there?This doesn’t log anything either:
Yeah i finally mastered Kotlin, i asked this when i was still wrapping my head round Kotlin. And frustration came in 😃
On Fri, Oct 26, 2018, 3:08 PM Ebenezer notifications@github.com wrote:
I’m closing this, because new “Exceptions” section in coroutines guide should address all the basic newbie questions.
Much easier it just using
deferred.await(). It will throw on failure and the exception (and failure) will get logged. You can do.forEach { it.await() }to get a test failure if any of them fails