Sobes.tech
Middle

Jaké způsoby zpracování chyb v korutinách znáte?

sobes.tech AI

Odpověď od AI

  • Použití bloků try...catch. Standardní způsob zpracování výjimek. Funguje uvnitř korutiny.

    // Použití try-catch
    suspend fun fetchData(): String {
        return try {
            // Operace, která může vyvolat výjimku
            throw Exception("Chyba při načítání dat")
            "Data úspěšně načtena"
        } catch (e: Exception) {
            "Chyba: ${e.message}"
        }
    }
    

    try...catch není vhodný pro zpracování uncaught výjimek, které jsou vyvolány z dceřiných korutin spuštěných v jiném CoroutineScope.

  • CoroutineExceptionHandler. Zachytává nezpracované výjimky, které jsou vyvolány korutinami spuštěnými v tomto CoroutineScope nebo v jeho dceřiných CoroutineScope.

    // CoroutineExceptionHandler
    val handler = CoroutineExceptionHandler { _, exception ->
        println("Zachycena výjimka: $exception")
    }
    
    // Použití CoroutineExceptionHandler
    GlobalScope.launch(handler) {
        // Korutina, která může vyvolat výjimku
        throw Exception("Chyba v korutině")
    }
    

    CoroutineExceptionHandler se aktivuje pouze pro výjimky, které nejsou zpracovány mechanismem strukturované konkurence.

  • SupervisorJob a supervisorScope. Na rozdíl od běžného Job, když dětská korutina s chybou způsobí zrušení rodičovského Job, SupervisorJob nezruší rodičovský Job. supervisorScope vytváří CoroutineScope s SupervisorJob.

    // Použití supervisorScope
    suspend fun loadMultipleData() = supervisorScope {
        val data1 = async {
            // Může vyvolat výjimku
            throw Exception("Chyba v datech 1")
            "Data 1"
        }
        val data2 = async {
            "Data 2"
        }
    
        // Zpracování výjimky pro konkrétní async
        try {
            println("Výsledek 1: ${data1.await()}")
        } catch (e: Exception) {
            println("Chyba při načítání dat 1: ${e.message}")
        }
        println("Výsledek 2: ${data2.await()}")
    }
    

    Používá se pro nezávislé podúkoly, kde chyba jednoho nemá vliv na ostatní. Nezastupuje try...catch nebo CoroutineExceptionHandler, spíše mění chování šíření výjimek.

  • Šíření výjimek ve strukturované konkurenci. Ve výchozím nastavení, výjimka v dětské korutině zruší rodičovskou korutinu a všechny její sourozence.

    // Příklad šíření výjimky
    runBlocking {
        val job = launch {
            launch { // Dětská korutina 1
                delay(100)
                throw Exception("Chyba v dětské 1")
            }
            launch { // Dětská korutina 2
                delay(200)
                println("Dětská 2 dokončena")
            }
        }
        try {
            job.join()
        } catch (e: Exception) {
            println("Výjimka zachycena v rodiči: $e")
        }
    }
    

    Toto je základní chování strukturované konkurence, které pomáhá předcházet únikům zdrojů a stavů.

  • Použití async s await(). Výjimky vyvolané v async se automaticky nešíří. Jsou uloženy uvnitř Deferred a vyhazují se pouze při volání await().

    // Zpracování výjimek s async/await
    suspend fun safeAsyncCall() = coroutineScope {
        val deferred = async {
            throw Exception("Chyba v async")
            "Výsledek async"
        }
    
        try {
            val result = deferred.await()
            println("Výsledek: $result")
        } catch (e: Exception) {
            println("Zachycena výjimka z async: ${e.message}")
        }
    }
    

    To umožňuje selektivně zpracovávat chyby pro každou asynchronní úlohu.

Způsob Účel Zachytí uncaught? Mění šíření?
try...catch Zpracování výjimek uvnitř aktuální korutiny Ne Ne
CoroutineExceptionHandler Zachytává ne zpracované výjimky v Scope Ano Ne
SupervisorJob/Scope Mění chování šíření výjimek Ne Ano
Strukturovaná konkurence Automatické zrušení při chybě Ano Ano
async + await() Odložené šíření výjimek Ne Ano (před await)