Exception handling

Unlike a pure job, deferred will not propagate unhandled exceptions automatically. It's done this way because it's expected that you will wait for the result of deferred, so it's up to you to validate that the execution was successful. Here's an example where deferred is not awaited:

fun main(args: Array<String>) = runBlocking {
val deferred = async {
TODO("Not implemented yet!")
}

// Wait for it to fail
delay(2000)
}

The preceding example will have deferred fail, but it will not propagate the exception. Here, we are using delay() so that we can reproduce an scenario in which we are not monitoring the execution of deferred—which you should never do—because deferred is intended to be monitored. Let's see how we can get the exception to propagate easily:

fun main(args: Array<String>) = runBlocking<Unit> {
val deferred = async {
TODO("Not implemented yet!")
}

// Let it fail
deferred.await()
}

This code, on the other hand, will have the exception propagate and will crash the application:

Deferred is designed this way because the idea is that by calling await(), you are indicating that the execution of deferred is an integral part of the code flow. Having it this way makes it easier to write asynchronous code that looks imperative, and it also allows for exception handling using a try-catch block:

fun main(args: Array<String>) = runBlocking<Unit> {
val deferred = async {
TODO("Not implemented yet!")
}

try {
deferred.await()
} catch (throwable: Throwable) {
println("Deferred cancelled due to ${throwable.message}")
}

}

You can also use the CoroutineExceptionHandler in the same way as when it was used for the job.

For the rest of this chapter, we will refer to both job and deferred as job since it's the base interface. Unless otherwise specified, everything that is said about job will apply to deferred as well.
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.133.152.198