Čo sa stane s korutínou, keď nastane výnimka?
sobes.tech AI
Odpoveď od AI
Pri pojave izuzetka unutar korutine, zavisno od tipa izuzetka (i podešavanja dispatcher-a/konteksta), odredjuje se kako će biti obrađen.
-
Nezavisni izuzetak: Ako izuzetak nije uhvaćen unutar korutine, on se propagira nagore kroz hijerarhiju korutina do najbližeg roditeljskog
Job(iliCoroutineScope). Ponašanje zavisi od tipaJob:Job: Po podrazumevanom, ako dođe do izuzetka u dečijoj korutini, roditeljskiJobse otkazuje, što dovodi do otkazivanja svih ostalih njegovih dečijih korutina. Izuzetak se prenosi nagore.SupervisorJob: Rodi-elskiSupervisorJobse ne otkazuje kada dođe do izuzetka u dečijoj korutini. Samo sama korutina u kojoj je došlo do izuzetka se otkazuje. Ovo je korisno kada je potrebno da otkazivanje jedne dečije zadatka ne utiče na ostale.- Korenski
CoroutineScope: Ako izuzetak dostigne korenskiCoroutineScope(npr.GlobalScopeili scope kreiran pomoćuCoroutineScopebezJob), on se prenosi u globalni obradač izuzetakaCoroutineExceptionHandler. Po podrazumevanom, ako nema registrovanog obradača, izuzetak se loguje uSystem.err.
-
Uhvaćen izuzetak: Ako je izuzetak uhvaćen pomoću
try-catchbloka unutar korutine, on se obrađuje lokalno, i korutina nastavlja sa izvršavanjem nakon blokacatch, ako je to moguće. Izuzetak se ne prenosi nagore. -
Izuzeci povezani sa otkazivanjem (npr.
CancellationException): Ovi izuzeci su posebni. Oni se koriste za mehanizam otkazivanja korutina i obično se ignorišu većinom obrađivača izuzetaka po podrazumevanom. Oni ne dovode do fatalnog pada roditeljskogJobpo podrazumevanom. -
Izuzeci u
async: Korutina pokrenuta pomoćuasyncpostavlja izuzetak u svojDeferred. Izuzetak se prenosi samo pri pozivu.await()na tomDeferred. Do tada je izuzetak "skriven".
import kotlinx.coroutines.*
fun main() = runBlocking {
val scope = CoroutineScope(SupervisorJob())
scope.launch {
try {
println("Korutina 1 počela")
delay(100)
throw RuntimeException("Nešto je pošlo po zlu u Korutini 1")
} catch (e: Exception) {
println("Uhvaćen izuzetak u Korutini 1: ${e.message}")
}
}
scope.launch {
println("Korutina 2 počela")
delay(500)
println("Korutina 2 završila")
}
delay(1000) // Čekamo da vidimo ispis
scope.cancel() // Otkažemo scope
}
U ovom primeru, izuzetak u Korutini 1 je uhvaćen, i Korutina 2 nastavlja sa izvršavanjem, jer je korišćen SupervisorJob. Ako bi bio korišćen običan Job, izuzetak u Korutini 1 bi doveo do otkazivanja Korutine 2.