Exception Handling

We'll cover the following

Many things can go wrong when making requests to web services, updating databases, accessing a file, and so on. When delegating a task to run asynchronously, we have to be defensive and handle failures gracefully. How we deal with exceptions depends on how we start a coroutine—using launch() or async().

Be Mindful of Structured Concurrency

Unless a scope is explicitly specified, coroutines run in the context and scope of their parent coroutines—called structured concurrency, where the hierarchical structure of coroutines matches the structure of code. This is a good thing as it’s easier to monitor and manage the execution of coroutines that we start. A coroutine doesn’t complete until all its children complete. But this also has some ramifications on how coroutines cooperate with each other and how failures are handled.

By default, when a coroutine fails with an exception, it results in the failure of the parent coroutine as well. Later in this chapter we’ll take a closer look at the behavior of coroutines in the context of structured concurrency and how we can prevent a child coroutine from cancelling a parent coroutine using a SupervisorJob context. In the examples in this section, we’ll use this context to prevent a child coroutine from cancelling its parent when an exception occurs.

launch and exceptions

If we use launch(), then the exception won’t be received on the caller side—it’s a fire and forget model, though you may optionally wait for the coroutine to complete. To illustrate this behavior and find a way to gracefully handle exceptions, let’s query the airport status using some invalid airport codes.

Get hands-on with 1200+ tech skills courses.