Real World Example

Swiggy Home Screen

When you open a food delivery app, the home screen needs the user profile, nearby restaurants and active offers. They come from three different services. Loading them one after another would make the user wait for the sum of all three; async loads them in parallel.

openHome()
  ├─ async → profileService      (250 ms)
  ├─ async → restaurantService   (400 ms)
  └─ async → offerService        (150 ms)
        ↓ awaitAll  (≈ 400 ms instead of 800 ms)
  render HomeScreen

Code

Example

A tiny version of that screen loader.

import kotlinx.coroutines.*
import kotlin.system.measureTimeMillis

data class Restaurant(val name: String, val etaMin: Int)
data class HomeScreen(val greeting: String, val restaurants: List<Restaurant>, val offers: List<String>)

suspend fun fetchProfile(userId: Int): String { delay(250); return "Priya" }
suspend fun fetchRestaurants(city: String): List<Restaurant> {
    delay(400)
    return listOf(Restaurant("Meghana Foods", 30), Restaurant("Truffles", 25), Restaurant("MTR", 40))
}
suspend fun fetchOffers(): List<String> { delay(150); return listOf("50% off up to 100", "Free delivery") }

suspend fun loadHome(userId: Int, city: String): HomeScreen = coroutineScope {
    val profile = async { fetchProfile(userId) }
    val restaurants = async { fetchRestaurants(city) }
    val offers = async { fetchOffers() }
    HomeScreen(
        greeting = "Hi ${profile.await()}!",
        restaurants = restaurants.await().sortedBy { it.etaMin },
        offers = offers.await(),
    )
}

fun main() = runBlocking {
    val time = measureTimeMillis {
        val home = loadHome(101, "Bengaluru")
        println(home.greeting)
        home.restaurants.forEach { println(" - ${it.name} (${it.etaMin} min)") }
        println("Offers: ${home.offers.joinToString()}")
    }
    println("Loaded in parallel (< 700 ms): ${time < 700}")
}

Output

Hi Priya!
 - Truffles (25 min)
 - Meghana Foods (30 min)
 - MTR (40 min)
Offers: 50% off up to 100, Free delivery
Loaded in parallel (< 700 ms): true

Tip: Wrapping the async calls in coroutineScope means: if one call fails, the others are cancelled and the error reaches the caller. You will learn this in the next module.