A suspending function is Kotlin’s core primitive for asynchronous work that may need to wait, such as a network request. Mark it with `suspend` to allow execution to pause and later continue without blocking the underlying thread. This preserves a direct, sequential style while other code can use the thread during the wait. section 14.4 section 14.4.1
Sequential code without thread blocking
```kotlin suspend fun login(credentials: Credentials): UserID suspend fun loadUserData(userID: UserID): UserData fun showData(data: UserData) suspend fun showUserInfo(credentials: Credentials) { val userID = login(credentials) val userData = loadUserData(userID) showData(userData) } ``` `login` and `loadUserData` may suspend while waiting for network responses. `showUserInfo` is also `suspend` because its calls can pause. `showData` remains ordinary because it does not need to pause. section 14.4.1 section 14.5.1
Suspension is not the same as blocking. Blocking leaves a thread unable to do useful work; suspension releases the thread for other work until the suspended computation can resume. This matters when many requests are waiting, or when blocking would freeze a user interface. section 14.4.1 section 14.0
A suspending function has clear calling rules:
- Call it from another suspending function; the caller can then propagate the possibility of suspension. section 14.5.1
- Call it from a coroutine, created by a coroutine builder such as `runBlocking`, `launch`, or `async`. section 14.6
- Do not call it directly from regular non-suspending code; Kotlin reports an error. section 14.5.1
Bridge regular code with runBlocking
```kotlin import kotlinx.coroutines.* import kotlin.time.Duration.Companion.milliseconds suspend fun doSomethingSlowly() { delay(500.milliseconds) println("I'm done") } fun main() = runBlocking { doSomethingSlowly() } ``` `runBlocking` creates a coroutine where suspending calls are allowed, but it blocks the calling thread until completion. It is a bridge from blocking code, not the general answer for avoiding blocked threads. section 14.6.1
For a dependent sequence of operations, plain suspending calls are enough. Use `async` only when independent computations should start concurrently and their `Deferred` results are later awaited. Unlike callbacks, futures, and reactive streams, basic suspending calls do not require wrapped return types or chaining operators. section 14.6.3 section 14.5
Listing 14.2 Using suspending functions to perform the same logic
suspend fun login(credentials: Credentials): UserID #1
suspend fun loadUserData(userID: UserID): UserData #1
fun showData(data: UserData) #1
suspend fun showUserInfo(credentials: Credentials) { #1
val userID = login(credentials)
val userData = loadUserData(userID)
showData(userData)
}
Compare the suspending version of `login`, `loadUserData`, and `showUserInfo`: adding `suspend` retains the original call order while allowing waiting operations to pause instead of block. section 14.4.1
