Exception-forplantning med async/await
Forstå hvordan exceptions fra async forplanter seg, og når try-await bør brukes.
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.
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
- SupervisorJob kontra Job: Isolere feil
- CoroutineExceptionHandler: Global uhåndtert handler
- Exception-forplantning med async/await
- Utforme robuste coroutine-arkitekturer