async/await-poikkeusten eteneminen
Ymmärtäkää, miten async-funktioiden poikkeukset etenevät ja milloin try-await-rakennetta käytetään.
async/await-poikkeusten eteneminen on ilmainen Kotlin Academy-oppitunti CoddyKitissä. Tämä on oppitunti 3/4. Voit lukea tästä oppimispolusta kokonaan mitkä tahansa 3 oppituntia ilmaiseksi — sen jälkeen CoddyKit PRO avaa kaikki oppitunnit sekä käytännön harjoittelun sisäänrakennetulla koodieditorilla ja ympäri vuorokauden toimivalla tekoälytuutorilla. Oppitunti kuuluu Kotlin Academy-oppimispolkuun, ja edistymisesi synkronoituu verkon ja CoddyKit-sovelluksen välillä. Kotlin Academy-kurssilla on yhteensä 4 oppituntia.
async tallentaa poikkeukset
Toisin kuin launch, async tallentaa poikkeuksen palautettuun Deferred-objektiin. Poikkeus heitetään uudelleen vasta, kun kutsutte 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}")
}
}Poikkeus ilman await()-kutsua
Jos ette koskaan kutsu await()-funktiota, poikkeus hylätään hiljaisesti tavallisen Job-vanhemman yhteydessä. Suosikaa rakennetta supervisorScope + käyttäkää aina await-kutsua.
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 coroutineScopen alla
Tavallisen coroutineScope-rakenteen alla async-lapsen heittämä poikkeus, joka välittyy eteenpäin eikä jää kiinni, peruuttaa scopen ja kaikki sisarukset.
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 supervisorScopen alla
supervisorScope-rakenteen alla async-poikkeukset EIVÄT välity sisaruksille. Jokainen await()` on käsiteltävä erikseen.
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 useille async-operaatioille
awaitAll(d1, d2, d3) odottaa kaikkia deferred-objekteja. Jos jokin epäonnistuu, se heittää poikkeuksen heti ja peruuttaa muut.
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 async-operaatioiden kanssa
Ympäröikää jokainen await()-kutsu runCatching-rakenteella, jotta voitte kerätä tulokset ja virheet ilman suorituksen keskeytymistä ensimmäiseen virheeseen.
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) }
}
}Rinnakkaiset tehtävät ja virheiden kerääminen
Kerätkää kaikki rinnakkaisten async-tehtävien epäonnistumiset ja ilmoittakaa niistä yhdessä sen sijaan, että suoritus epäonnistuisi heti ensimmäiseen virheeseen.
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}")
}Poikkeustyypin säilyminen
async-rakenteen sisällä heitetyt poikkeukset säilyttävät tyyppinsä. Ottakaa await()-kutsun yhteydessä kiinni täsmällisestä poikkeustyypistä, jotta voitte käsitellä virheen tarkasti.
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() ei-keskeyttävään tarkistukseen
Käyttäkää join()-kutsun jälkeen getCompleted()-funktiota tuloksen hakemiseen synkronisesti. Se heittää poikkeuksen, jos deferred epäonnistui.
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}")
}
}Rakenteinen samanaikaisuus ja async
Rakenteisessa samanaikaisuudessa async-deferred on aina linkitetty vanhempaan scopeensa. Kun scope peruutetaan, myös deferred peruutetaan — orpoja tehtäviä ei synny.
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") }
}Paras käytäntö: odottakaa aina
Kutsukaa aina await()-funktiota jokaiselle async-deferredille, vaikka ette tarvitsisi tulosta. Näin poikkeukset tulevat näkyviin ja hiljaiset epäonnistumiset estetään.
import kotlinx.coroutines.*
fun main() = runBlocking {
supervisorScope {
val d = async {
// do background work
"done"
}
// Always await:
val result = runCatching { d.await() }
println(result)
}
}Pikatarkistus
Milloin async { throw ... } -lohkon poikkeus tulee näkyviin?
Kertaus
async tallentaa poikkeukset Deferred-objektiin, ja ne tulevat näkyviin await()-kutsun yhteydessä. coroutineScope-rakenteen alla välittyminen peruuttaa sisarukset. supervisorScope-rakenteen alla jokaisen await-kutsun on käsiteltävä oma epäonnistumisensa. Odottakaa aina jokaista deferred-objektia.
Opi Kotlin tekoälytuutorin avulla — ilmaiseksi
Kirjoita ja suorita oikeaa koodia selaimessa, saa välitöntä apua tekoälytuutorilta ympäri vuorokauden ja jatka siitä, mihin jäit, verkossa tai sovelluksessa.
- Kurssit
- 51
- Oppitunnit
- 203
Usein kysytyt kysymykset
Onko oppitunti ”async/await-poikkeusten eteneminen” ilmainen?
Kyllä — voit lukea täällä verkossa kokonaan ilmaiseksi mitkä tahansa Kotlin Academy-oppimispolun 3 oppituntia, myös oppitunnin “async/await-poikkeusten eteneminen”. Sen jälkeen CoddyKit PRO avaa kaikki oppitunnit sekä interaktiiviset harjoitukset sisäänrakennetulla koodieditorilla ja ympäri vuorokauden toimivalla tekoälytuutorilla. Kotlin Academy-kurssilla on yhteensä 4 oppituntia.
Mitä opin oppitunnilla ”async/await-poikkeusten eteneminen”?
Ymmärtäkää, miten async-funktioiden poikkeukset etenevät ja milloin try-await-rakennetta käytetään. Harjoittelet Kotlin Academy-aihetta koodilla, jonka suoritat suoraan selaimessa. Ympäri vuorokauden käytettävissä oleva tekoälytuutori vastaa kysymyksiisi oppitunnin aikana.
Tarvitsenko kokemusta aloittaakseni Kotlin Academy-opiskelun?
Aiempi kokemus ei ole tarpeen. CoddyKitin Kotlin Academy-oppimispolku sopii vasta-alkajista edistyneisiin, joten voit aloittaa tästä tai alusta ja edetä omaan tahtiisi. Tämä on oppitunti 3/4.
Kuinka kauan ”async/await-poikkeusten eteneminen”-oppitunnin suorittaminen kestää?
Useimmat CoddyKitin oppitunnit kestävät noin 5–10 minuuttia. Jokainen oppitunti on lyhyt ja interaktiivinen, joten edistyt tasaisesti ja voit jatkaa siitä, mihin jäit – sekä verkossa että sovelluksessa.
Voinko kirjoittaa ja suorittaa koodia tällä Kotlin Academy-oppitunnilla?
Kyllä. Jokainen Kotlin Academy-oppitunti sisältää sisäänrakennetun koodieditorin, joten voit kirjoittaa ja suorittaa oikeaa koodia suoraan selaimessa ja saada välitöntä palautetta tekoälyltä – paikallista asennusta ei tarvita.
Kaikki tämän kurssin oppitunnit
- SupervisorJob vs Job: virheiden eristäminen
- CoroutineExceptionHandler: maailmanlaajuinen käsittelemätön poikkeusten käsittelijä
- async/await-poikkeusten eteneminen
- Vikasietoisten korutiiniarkkitehtuurien suunnittelu