Kotlin Academy · leksjon

Exception-forplantning med async/await

Forstå hvordan exceptions fra async forplanter seg, og når try-await bør brukes.

Leksjon 3 av 413 trinn

Exception-forplantning med async/await er en gratis leksjon i Kotlin Academy på CoddyKit. Dette er leksjon 3 av 4. Du kan lese valgfritt 3 leksjoner fra denne læringsstien gratis i sin helhet – deretter låser CoddyKit PRO opp alle leksjoner, samt praktisk øving med en innebygd kodeeditor og en AI-veileder som er tilgjengelig døgnet rundt. Den er en del av læringsløpet i Kotlin Academy, og fremdriften din synkroniseres mellom nettet og CoddyKit-appen. Kurset i Kotlin Academy inneholder totalt 4 leksjoner.

async lagrer unntak

I motsetning til launch lagrer async unntaket i den returnerte Deferred. Det kastes først på nytt når du kaller await().

import kotlinx.coroutines.*
fun main() = runBlocking {
    val deferred = async {
        throw RuntimeException("async error")
    }
    try {
        deferred.await()  // exception rethrown here
    } catch (e: RuntimeException) {
        println("Caught: ${e.message}")
    }
}

Unntak uten await()

Hvis du aldri kaller await(), forkastes unntaket stille med en vanlig Job-forelder. Foretrekk supervisorScope + await alltid.

import kotlinx.coroutines.*
fun main() = runBlocking {
    // Exception stored in deferred, never retrieved:
    val d = async { throw RuntimeException("lost exception") }
    delay(100)  // d has failed — exception never surfaced
    println("d.isCancelled: ${d.isCancelled}")
}

async under coroutineScope

Under et vanlig coroutineScope kansellerer et async-barn som kaster et unntak, scopet og alle søsknene dersom unntaket propageres (ikke fanges).

import kotlinx.coroutines.*
fun main() = runBlocking {
    try {
        coroutineScope {
            val a = async { "A" }
            val b = async { throw RuntimeException("B failed") }
            println(a.await())
            println(b.await())  // propagates, cancels scope
        }
    } catch (e: RuntimeException) {
        println("Scope failed: ${e.message}")
    }
}

async under supervisorScope

Under supervisorScope propageres unntak fra async() IKKE til søsknene. Hver await()` må pakkes inn individuelt.

import kotlinx.coroutines.*
fun main() = runBlocking {
    supervisorScope {
        val a = async { "A" }
        val b = async { throw RuntimeException("B failed") }
        println(a.await())
        try { println(b.await()) }
        catch (e: RuntimeException) { println("b failed: ${e.message}") }
    }
}

awaitAll for flere async

awaitAll(d1, d2, d3) venter på alle deferred-objektene. Hvis ett av dem feiler, kaster funksjonen umiddelbart et unntak og kansellerer de andre.

import kotlinx.coroutines.*
fun main() = runBlocking {
    try {
        val results = awaitAll(
            async { "result1" },
            async { throw RuntimeException("task 2 failed") },
            async { "result3" }
        )
        println(results)
    } catch (e: Exception) {
        println("awaitAll failed: ${e.message}")
    }
}

runCatching med async

Pakk hver await() inn i runCatching for å samle resultater og feil uten å avbryte ved første feil.

import kotlinx.coroutines.*
fun main() = runBlocking {
    supervisorScope {
        val deferreds = listOf(
            async { "A" },
            async { throw RuntimeException("B") },
            async { "C" }
        )
        val results = deferreds.map { runCatching { it.await() } }
        results.forEach { println(it) }
    }
}

Parallelle oppgaver med akkumulering av feil

Samle alle feil fra parallelle async-oppgaver og rapporter dem samlet i stedet for å feile raskt.

import kotlinx.coroutines.*
fun main() = runBlocking {
    val tasks = listOf("a", "b", "c")
    val results = supervisorScope {
        tasks.map { t ->
            async {
                if (t == "b") throw RuntimeException("b failed")
                t.uppercase()
            }
        }.map { runCatching { it.await() } }
    }
    val errors = results.filter { it.isFailure }
    val successes = results.mapNotNull { it.getOrNull() }
    println("Success: $successes, Errors: ${errors.size}")
}

Bevaring av unntakstype

Unntak som kastes inne i async, beholder typen sin. Fang den spesifikke unntakstypen ved await() for presis feilhåndtering.

import kotlinx.coroutines.*
class NetworkException(msg: String) : RuntimeException(msg)
fun main() = runBlocking {
    val d = async { throw NetworkException("timeout") }
    try {
        d.await()
    } catch (e: NetworkException) {
        println("Network error: ${e.message}")
    } catch (e: Exception) {
        println("Other error: ${e.message}")
    }
}

Deferred.getCompleted() for kontroll uten suspendering

Etter join() kan du bruke getCompleted() til å hente resultatet synkront. Den kaster et unntak hvis den deferred-en feilet.

import kotlinx.coroutines.*
fun main() = runBlocking {
    val d = async { 42 }
    d.join()  // wait without caring about result
    try {
        val result = d.getCompleted()  // synchronous — no suspend
        println("Result: $result")
    } catch (e: Exception) {
        println("Failed: ${e.message}")
    }
}

Strukturert samtidighet og async

Med strukturert samtidighet er en async-deferred alltid knyttet til foreldrescopet sitt. Når scopet kanselleres, kanselleres også deferred-en – ingen foreldreløse oppgaver.

import kotlinx.coroutines.*
fun main() = runBlocking {
    val scope = CoroutineScope(SupervisorJob())
    val d = scope.async {
        delay(1000)
        "result"
    }
    scope.cancel()  // cancels d too
    try { d.await() }
    catch (e: CancellationException) { println("Cancelled as expected") }
}

Beste praksis: Await alltid

Kall alltid await() på alle async-deferred-objekter, selv om du ikke trenger resultatet. Da blir unntak synlige, og stille feil unngås.

import kotlinx.coroutines.*
fun main() = runBlocking {
    supervisorScope {
        val d = async {
            // do background work
            "done"
        }
        // Always await:
        val result = runCatching { d.await() }
        println(result)
    }
}

Hurtigsjekk

Når blir unntaket fra en async { throw ... }-blokk synlig?

Oppsummering

async lagrer unntak i Deferred; de blir synlige ved await(). Under coroutineScope kansellerer propagering søsknene. Under supervisorScope må hvert await håndtere sin egen feil. Await alltid alle deferred-objekter.

Gratis å komme i gang

Lær deg Kotlin med en AI-veileder – gratis

Skriv og kjør ekte kode i nettleseren, få umiddelbar hjelp fra en AI-veileder som er tilgjengelig døgnet rundt, og fortsett der du slapp – på nettet eller i appen.

Kurs
51
Leksjoner
203

Ofte stilte spørsmål

Er leksjonen «Exception-forplantning med async/await» gratis?

Ja – du kan lese valgfritt 3 av leksjonene i læringsstien Kotlin Academy, inkludert «Exception-forplantning med async/await», gratis i sin helhet her på nettet. Deretter låser CoddyKit PRO opp alle leksjoner, samt interaktiv øving med en innebygd kodeeditor og en AI-veileder som er tilgjengelig døgnet rundt. Kurset i Kotlin Academy inneholder totalt 4 leksjoner.

Hva lærer jeg i «Exception-forplantning med async/await»?

Forstå hvordan exceptions fra async forplanter seg, og når try-await bør brukes. Du øver på Kotlin Academy med praktisk kode som du kjører direkte i nettleseren, mens en AI-veileder som er tilgjengelig døgnet rundt, svarer på spørsmålene dine mens du jobber deg gjennom leksjonen.

Trenger jeg erfaring for å begynne med Kotlin Academy?

Ingen tidligere erfaring er nødvendig. Kotlin Academy på CoddyKit er lagt opp for både nybegynnere og viderekomne, så De kan begynne her eller helt fra start og lære i Deres eget tempo. Dette er leksjon 3 av 4.

Hvor lang tid tar leksjonen «Exception-forplantning med async/await»?

De fleste CoddyKit-leksjoner tar omtrent 5–10 minutter. Hver leksjon er kort og interaktiv, slik at De gjør jevne fremskritt og kan fortsette akkurat der De slapp – både på nettet og i appen.

Kan jeg skrive og kjøre kode i denne Kotlin Academy-leksjonen?

Ja. Alle Kotlin Academy-leksjoner har en innebygd kodeeditor, slik at De kan skrive og kjøre ekte kode direkte i nettleseren og få umiddelbar tilbakemelding fra AI – uten lokal konfigurering.

Alle leksjonene i dette kurset

  1. SupervisorJob kontra Job: Isolere feil
  2. CoroutineExceptionHandler: Global uhåndtert handler
  3. Exception-forplantning med async/await
  4. Utforme robuste coroutine-arkitekturer
← Tilbake til Kotlin Academy