Sobes.tech
Middle

Šta se dešava sa korutinom kada dođe do izuzetka?

sobes.tech АИ

Одговор од АИ

Када се појави изузетак унутар корутине, зависност од типа изузетка (и подешавања диспетчера/контекста) одређује како ће бити обрађен.

  • Неконтролисани изузетак: Ако изузетак није ухваћен унутар корутине, он се пропагира нагоре кроз хијерархију корутина до најближег родитељског Job (или CoroutineScope). Понашање зависи од типа Job:

    • Job: По подразумевану, ако дође до изузетка у дечијој корути, родитељски Job се отказује, што доводи до отказивања свих осталих дечијих корутина. Изузетак се преноси горе.
    • SupervisorJob: Родитељски SupervisorJob се не отказује када дође до изузетка у дечијој корути. Само сама корутина у којој је дошло до изузетка се отказује. Ово је корисно када је потребно да отказивање једне дечије задаће не утиче на друге.
    • Коренски CoroutineScope: Ако изузетак достигне коренски CoroutineScope (нпр. GlobalScope или scope креиран помоћу CoroutineScope без Job), он се преноси у глобални обработљач изузетака CoroutineExceptionHandler. По подразумевану, ако нема регистрованог обработљача, изузетак се логова у System.err.
  • Хваћени изузетак: Ако је изузетак ухваћен помоћу try-catch блока унутар корутине, он се обрађује локално, и корутина наставља са извршавањем након блока catch, ако је то могуће. Изузетак се не преноси горе.

  • Изузетци везани за отказивање (нпр. CancellationException): Ови изузетци су посебни. Користе се за механизам отказивања корутина и обично се игноришу од стране већине обработљача изузетака по подразумеваној. Они не доводе до фаталног пада родитељског Job по подразумеваној.

  • Изузетци у async: Корутине покренуте помоћу async стављају изузетак у свој Deferred. Изузетак се преноси само при позиву .await() на том Deferred. До тада је изузетак "скривен".

import kotlinx.coroutines.*

fun main() = runBlocking {
    val scope = CoroutineScope(SupervisorJob())

    scope.launch {
        try {
            println("Корутинa 1 започела")
            delay(100)
            throw RuntimeException("Нешто је пошло по злу у Корутинa 1")
        } catch (e: Exception) {
            println("Хваћен изузетак у Корутинa 1: ${e.message}")
        }
    }

    scope.launch {
        println("Корутинa 2 започела")
        delay(500)
        println("Корутинa 2 завршена")
    }

    delay(1000) // Чекамо да видимо излаз
    scope.cancel() // Отказујемо scope
}

У овом примеру, изузетак у Корутинa 1 је хваћен, и Корутинa 2 наставља са извршавањем, јер је коришћен SupervisorJob. Ако би био коришћен обичан Job, изузетак у Корутинa 1 би довео до отказивања Корутинa 2.