What does the async coroutine builder return, and how do you get the result out of it?
answer
- async returns Deferred<T>
- await() suspends to get value
- launch=Job, async=Deferred
- starts eagerly by default
- await rethrows the exception
basics
~10 sasync starts a background task and hands you a Deferred. You call await() on it to wait for and receive the result value.
solid answer
~40 sasync is a coroutine builder on CoroutineScope that starts a new coroutine and immediately returns a Deferred<T> — a future-like handle. The coroutine runs concurrently; you don't get the value back from async itself. To obtain the computed value you call the suspending function await() on the Deferred, which suspends the caller until the result is ready and then returns it (or rethrows any exception the coroutine threw). Use async when you want a value back; use launch when you only need a side effect (it returns Job, not Deferred). Both start eagerly by default. await() does not block a thread — it suspends, so other work can proceed on the same thread.
code
kotlin · 4 linessuspend fun price(): Int = coroutineScope {
val d: Deferred<Int> = async { 21 * 2 }
d.await() // 42
}go deeper
Knows async returns Deferred and await() retrieves the value; distinguishes it from launch.
Explains suspension vs blocking and eager start, and that await rethrows exceptions.
Frames async as scope-bound structured concurrency and notes CoroutineStart.LAZY and Deferred-is-a-Job.
Discusses when returning Deferred across API boundaries is appropriate vs keeping it internal to a scope.
## What `async` is `async` is a **coroutine builder**: a function that starts a new coroutine. It is an extension on `CoroutineScope`. Unlike `launch` (which returns a `Job` and is used for fire-and-forget side effects), `async` returns a **`Deferred<T>`**. ## `Deferred<T>` `Deferred<T>` is a `Job` that also carries a **future result** of type `T`. Think of it as a promise/future: a handle to a value that will exist later. Because `Deferred` *is a* `Job`, it also has lifecycle methods like `cancel()` and `isActive`. ## `await()` To read the value you call `await()`, a **suspending function**. "Suspending" means it can pause the current coroutine without blocking the underlying thread, freeing that thread for other work, and resume later when the result is ready. - If the coroutine already finished, `await()` returns immediately. - If it is still running, `await()` **suspends** until completion. - If the coroutine threw, `await()` **rethrows** that exception. ```kotlin suspend fun loadUser(): User = coroutineScope { val deferred: Deferred<User> = async { fetchUserFromDb() } // starts now // ... can do other work here while it runs ... deferred.await() // suspend until the value is ready, then return it } ``` ## Eager start By default `async` uses `CoroutineStart.DEFAULT`, so the coroutine begins **eagerly** as soon as `async` is called — not lazily when `await()` is invoked. (You can pass `start = CoroutineStart.LAZY` to defer it until `await()` or `start()`.) ## Key keywords/APIs - `async { ... }` — builder returning `Deferred<T>` - `Deferred<T>` — future-like Job carrying a result - `await()` — suspends to obtain the value or rethrow - contrast `launch` → `Job` (no result)
- What does launch return instead, and when would you use it?launch returns a Job (no result value). Use it for fire-and-forget side effects where you don't need a return value.
- Does calling await() block the thread?No. await() is a suspending function: it suspends the coroutine and frees the thread; it doesn't block it.
async is a coat-check ticket: you hand off work, get a ticket (Deferred), and redeem it later with await().
saying these in an interview costs you the question
- Saying async returns the value directly instead of a Deferred
- Claiming await() blocks the calling thread
- Confusing async (Deferred) with launch (Job)
- Thinking async only starts when await() is called (it's eager by default)