async: wat is het, Deferred en parallelle coroutines hoe ze werken

Auteur: IT Sectr Gepubliceerd: 2026-06-22 Leestijd: 8 min

async — Coroutine Builder in Kotlin die een coroutine start en een Deferred<T>-object retourneert om het resultaat van een asynchrone bewerking te verkrijgen. async maakt het mogelijk om meerdere taken parallel uit te voeren en hun resultaten te aggregeren via await(). Volgens de JetBrains-gids, 2024, is async de voorkeursmethode voor het organiseren van parallelle berekeningen in coroutines.

Belangrijkste

  • async — coroutine-bouwer die Deferred<T> retourneert met het resultaat van een asynchrone bewerking
  • Deferred — asynchrone belofte, die Job erft, met de methode await() om het resultaat te verkrijgen
  • async maakt parallelle uitvoering van onafhankelijke taken mogelijk, waardoor de totale tijd wordt verkort
  • await() — suspend-functie die de coroutine onderbreekt totdat het resultaat is verkregen zonder blokkering
  • Gestructureerde concurrentie met async garandeert annulering van alle parallelle taken bij een fout

Wat is async in Kotlin Coroutines?

async — is een extensiefunctie van CoroutineScope die een coroutine met resultaatretour creëert. In tegenstelling tot launch retourneert async Deferred<T> — een object dat een toekomstige waarde vertegenwoordigt. De via async gestarte coroutine wordt concurrent met andere coroutines uitgevoerd, wat parallellisatie van berekeningen mogelijk maakt.

async wordt gebruikt wanneer het resultaat van een asynchrone bewerking nodig is voor verdere verwerking: het laden van gegevens uit meerdere bronnen, batchverwerking van collecties, parallelle aanvragen naar verschillende API's. Deferred wordt onmiddellijk aangemaakt en het resultaat wordt beschikbaar na voltooiing van de coroutine.

kotlin
import kotlinx.coroutines.*

suspend fun String.delayedValue(): String {
    delay(1000L)
    return this
}

fun main() = runBlocking {
    val deferred: Deferred<String> = async { "Hello".delayedValue() }
    println(deferred.await())
}

Syntaxis van async en Deferred

De handtekening van async is vergelijkbaar met launch: dezelfde parameters CoroutineContext, CoroutineStart en suspend-blok. Het verschil zit in het retourtype — Deferred<T> in plaats van Job, waarbij T het type is van het resultaat dat door de laatste expressie van het blok wordt geretourneerd.

kotlin
public fun <T> CoroutineScope.async(
    context: CoroutineContext = EmptyCoroutineContext,
    start: CoroutineStart = CoroutineStart.DEFAULT,
    block: suspend CoroutineScope.() -> T
): Deferred<T>

Deferred<T> — interface die Job erft en de methoden await(), getCompleted(), getCompletionExceptionOrNull() toevoegt. await() is een suspend-functie en kan alleen binnen een coroutine of een andere suspend-functie worden aangeroepen. getCompleted() — een niet-blokkerende methode die een uitzondering gooit als de coroutine nog niet is voltooid.

Parallelle taken met async

Het belangrijkste voordeel van async is de mogelijkheid om taken parallel te starten. In plaats van sequentieel wachten op elke bewerking (totale tijd = som van tijden), start async coroutines gelijktijdig, waardoor de totale tijd wordt teruggebracht tot de tijd van de langste bewerking.

Parallel gegevens laden

Een typisch scenario — het laden van het gebruikersprofiel, de instellingen en de bestelgeschiedenis met drie parallelle async-verzoeken. Na voltooiing van alle drie worden de resultaten samengevoegd in één gegevensmodel.

kotlin
suspend fun loadUserDashboard(userId: String): Dashboard = coroutineScope {
    val profile = async { api.getProfile(userId) }
    val settings = async { api.getSettings(userId) }
    val orders = async { api.getRecentOrders(userId) }

    Dashboard(
        profile = profile.await(),
        settings = settings.await(),
        orders = orders.await()
    )
}

De functie coroutineScope start onderliggende coroutines en wacht op hun voltooiing voordat het resultaat wordt geretourneerd. Het hele blok wordt parallel uitgevoerd, niet sequentieel.

Verwerking van Deferred-resultaten

Deferred ondersteunt verschillende methoden voor het werken met het resultaat. Naast await() zijn er methoden voor statuscontrole, het ophalen van de gereed zijnde waarde en aggregatie van meerdere Deferred via de hulpfuncties van Kotlin Coroutines.

MethodeBeschrijvingSuspend?
await()Onderbreekt de coroutine totdat het resultaat is verkregenJa
getCompleted()Retourneert het resultaat als de coroutine is voltooid (anders Exception)Nee
getCompletionExceptionOrNull()Retourneert de uitzondering bij een fout of nullNee
isCompletedControleert of de coroutine is voltooidNee

Voor aggregatie van een lijst met Deferred wordt awaitAll() gebruikt — een functie die de uitvoering onderbreekt totdat alle Deferred in de collectie zijn voltooid. Als er minstens één met een fout is geëindigd, gooit awaitAll() een uitzondering.

kotlin
suspend fun <T> loadAll(requests: List<suspend () -> T>): List<T> {
    return coroutineScope {
        val deferreds = requests.map { async { it() } }
        deferreds.awaitAll()
    }
}

Verschillen tussen async en launch

De keuze tussen async en launch hangt af van of het resultaat van de coroutine-uitvoering nodig is. launch retourneert Job en is geschikt voor fire-and-forget-bewerkingen, async retourneert Deferred en wordt gebruikt voor taken die gegevens retourneren. Qua syntaxis en parameters zijn de bouwers identiek.

  • launch → Job (geen resultaat), async → Deferred<T> (heeft resultaat T)
  • launch — fire-and-forget-taken (loggen, cachen, analyses verzenden)
  • async — parallelle berekeningen (laden van meerdere API's, batchverwerking)
  • Beide ondersteunen gestructureerde concurrentie en CoroutineStart-parameters
  • await() is alleen beschikbaar voor Deferred, launch levert geen resultaat

Belangrijke regel: gebruik async nooit voor fire-and-forget. Als het resultaat van de coroutine niet nodig is, gebruik dan launch. async creëert overhead voor het maken van Deferred, wat in een dergelijk scenario niet gerechtvaardigd is.

Voorbeelden van async in mobiele ontwikkeling

In Android wordt async gebruikt voor parallelle bewerkingen binnen ViewModel en UseCases. Typische scenario's: gelijktijdig laden van profiel en nieuwsfeed, ophalen van weer van meerdere weerdiensten, batch-synchronisatie van gegevens met de server.

kotlin
class HomeViewModel : ViewModel() {
    fun loadHomeScreen() {
        viewModelScope.launch {
            val userData = async(Dispatchers.IO) { repository.getUserData() }
            val newsFeed = async(Dispatchers.IO) { repository.getNewsFeed() }
            val notifications = async(Dispatchers.IO) { repository.getNotifications() }

            val state = HomeState(
                user = userData.await(),
                news = newsFeed.await(),
                unread = notifications.await()
            )
            _uiState.update { state }
        }
    }
}

Het wordt aanbevolen om een groep async in coroutineScope of supervisorScope te wrappen voor foutisolatie. supervisorScope maakt het mogelijk om de uitvoering van de overige async-coroutines voort te zetten, zelfs als er een fout optreedt in één ervan — nuttig voor niet-kritieke bewerkingen.

Veelgestelde vragen

Kan async zonder await worden gebruikt?

Het kan, maar het is zinloos. async zonder await() start de coroutine, maar het resultaat gaat verloren. Als het resultaat niet nodig is, gebruik dan launch — het maakt geen Deferred aan en is efficiënter qua geheugen en prestaties.

Hoe gaat async om met uitzonderingen?

De uitzondering binnen async wordt opgeslagen in Deferred. De aanroep await() gooit deze uitzondering door. Gebruik getCompletionExceptionOrNull() om te controleren zonder door te gooien. Bij gebruik van coroutineScope annuleert de fout alle onderliggende coroutines.

Wat is awaitAll in Kotlin Coroutines?

awaitAll() — een extensiefunctie voor Iterable<Deferred<T>> die de coroutine onderbreekt totdat alle Deferred zijn voltooid. Retourneert een lijst met resultaten. Als ten minste één Deferred met een fout eindigt, gooit het de uitzondering door en annuleert de rest.

Verschilt async van GlobalScope.async?

Ja. async is een extensiefunctie van CoroutineScope, gebonden aan de scope. GlobalScope.async maakt een coroutine zonder binding aan de levenscyclus — deze kan oneindig worden uitgevoerd. In Android wordt GlobalScope afgeraden vanwege het risico op geheugenlekken.

Hoeveel async-coroutines kunnen worden gestart voor parallelle verzoeken?

Het aantal wordt bepaald door de dispatcher: Dispatchers.IO ondersteunt tot 64 gelijktijdige threads, Dispatchers.Default — op basis van het aantal CPU-kernen. Gebruik voor massale bewerkingen beperkte parallelliteit via Semaphore of mapNotNull met awaitAll.

Samenvatting

  • async — coroutine-bouwer die Deferred<T> retourneert voor asynchrone resultaatverkrijging
  • Deferred erft Job en voegt de methoden await(), getCompleted(), getCompletionExceptionOrNull() toe
  • Parallelle uitvoering met async verkort de totale tijd tot de duur van de langste bewerking
  • awaitAll() — hulpmiddel om te wachten op alle Deferred in een collectie
  • coroutineScope — aanbevolen wrapper voor een groep async met annuleringsgarantie
  • Gebruik async niet voor fire-and-forget — pas launch toe
  • In Android wordt async gebruikt voor parallel laden in ViewModel met viewModelScope

We ontwikkelen een mobiele applicatie turnkey

IT Sectr creëert sinds 2017 iOS- en Android-applicaties voor startups en bedrijven. We adviseren u en stellen de beste oplossing voor.

Bespreek het project

Lees ook