`async` starts a coroutine that computes a value asynchronously and returns `Deferred<T>`. Call the suspending `await()` function on that handle to obtain the value. Unlike `launch`, which is suited to start-and-forget side effects, `async` is for work whose result will be consumed. section 14.6.3 section 14.6.3
Start independent work together
```kotlin fun main() = runBlocking { val first = async { slowlyAddNumbers(2, 2) } val second = async { slowlyAddNumbers(4, 4) } println(first.await()) println(second.await()) } ``` Each `async` call starts a new coroutine without suspending the caller. The caller suspends at `await()` only until that particular result is ready. When the computations are independent, both delays can overlap, so total time is roughly that of the longest computation rather than their sum. section 14.6.3 section 14.6.3
Use `async` deliberately rather than wrapping every suspending call. Sequential suspending calls already express sequential work without blocking the underlying thread. `async` adds value when tasks can begin independently and their results are needed later, such as loading two images before combining them. section 14.6.3 section 1.2.4
suspend fun loadAndOverlay(first: String, second: String): Image =
coroutineScope {
val firstDeferred = async { loadImage(first) } #1
val secondDeferred = async { loadImage(second) } #2
combineImages(firstDeferred.await(), secondDeferred.await()) #3
}
This example shows the usual result-oriented pattern: create two `Deferred` values in one `coroutineScope`, await both, then combine their completed values. section 1.2.4
An `async` coroutine belongs to a `CoroutineScope`. When started inside another coroutine builder, it becomes a child coroutine, so structured concurrency tracks it as part of the parent’s lifetime. This relationship also matters for failure: an uncaught child exception propagates to its parent and can cancel sibling coroutines in a regular, nonsupervisor scope. section 15.1 section 18.2.1
Treat `await()` as an error boundary for a deferred result. If the `async` block fails, `await()` rethrows that exception because no value of the expected type is available; surround `await()` with `try-catch` when the consumer handles it. Catching only around the `async` call does not catch an exception thrown later inside its new coroutine. section 18.1 section 18.1
A top-level `async` has a distinct exception-handling role: `CoroutineExceptionHandler` is not invoked for it. The consumer of its `Deferred` is responsible for observing failure through `await()`, though uncaught failure can still trigger cancellation unless a `SupervisorJob` changes that scope behavior. section 18.3.1 section 18.3.1
