Handling multiple requests with async coroutine builder in Kotlin
In this previous article, we introduced the launch
coroutine builder to start a coroutine that doesn’t have a result. When your task has a result that you want to use you can use the async
coroutine builder.
async
is useful in scenarios where you make multiple API requests that can be run concurrently and combined once all have finished - this is a common scenario in microservice architectured backends for example. By performing the operations concurrently we can return the combined response sooner as we are not wasting time waiting for the first operation to finish before moving on to the next.
Async Coroutine Syntax
The basic syntax of the async
coroutine builder is similar to launch
, i.e. pass a block of code to execute. async
returns an instance of Deferred<T>
which represents the deferred result of the coroutine, similar to a Promise
in Javascript. Deferred<T>
has a method called await
that will wait for the coroutine to complete and return the result.
val deferredResult = async {
fetchData()
}
// you can perform other tasks while waiting for the coroutine to complete
val result = deferredResult.await()
Real World Example
In the example below we start two async requests to get the user’s bank balance and transactions. These two requests are independent so they can run concurrently, we do however want to wait for both requests to be completed before printing the results. You can imagine this sort of code in an API that gathers and summarises a user’s finances, the requests must have been completed to send the response to the client.
suspend fun fetchBalance(): BigDecimal {
delay(500)
return "1200.00".toBigDecimal()
}
suspend fun fetchTransactions(): List<BigDecimal> {
delay(1000)
return listOf(
"50.00".toBigDecimal(),
"75.00".toBigDecimal()
)
}
fun main() = runBlocking {
val balanceDeferred = async { fetchBalance() }
val transactionsDeferred = async { fetchTransactions() }
val balance = balanceDeferred.await()
val transactions = transactionsDeferred.await()
println("Balance: $balance")
println("Total Spending: ${transactions.sumOf { it }}")
}
The output is printed:
println("Balance: 100.00")
println("Total Spending: 125.00")