Sobes.tech
Middle

Aké spôsoby spracovania chýb v korutinách poznáte?

sobes.tech AI

Odpoveď od AI

  • Použitie try...catch blokov. Štandardný spôsob spracovania výnimiek. Funguje vo vnútri korutiny.

    // Použitie try-catch
    suspend fun fetchData(): String {
        return try {
            // Operácia, ktorá môže vyhodiť výnimku
            throw Exception("Chyba pri načítaní dát")
            "Dáta úspešne načítané"
        } catch (e: Exception) {
            "Chyba: ${e.message}"
        }
    }
    

    try...catch nie je vhodný na spracovanie nechytených výnimiek, ktoré sú vyhodené z dcérskych korútín, spustených v inom CoroutineScope.

  • CoroutineExceptionHandler. Zachytáva neopracované výnimky, ktoré sú vyhodené korutínami, ktoré sú spustené v tomto CoroutineScope alebo v jeho dcérskych CoroutineScope.

    // CoroutineExceptionHandler
    val handler = CoroutineExceptionHandler { _, exception ->
        println("Zachytená výnimka: $exception")
    }
    
    // Použitie CoroutineExceptionHandler
    GlobalScope.launch(handler) {
        // Korutína, ktorá môže vyhodiť výnimku
        throw Exception("Chyba v korutíne")
    }
    

    CoroutineExceptionHandler sa aktivuje iba pre výnimky, ktoré nie sú spracované mechanizmom štruktúrovanej konkurencie.

  • SupervisorJob a supervisorScope. Na rozdiel od obyčajného Job, keď dcérska korutína s chybou vedie k zrušeniu rodičovského Job, SupervisorJob nezruší rodičovský Job pri chybe dcérskej korutiny. supervisorScope vytvára CoroutineScope s SupervisorJob.

    // Použitie supervisorScope
    suspend fun loadMultipleData() = supervisorScope {
        val data1 = async {
            // Môže vyhodiť výnimku
            throw Exception("Chyba v dátach 1")
            "Dáta 1"
        }
        val data2 = async {
            "Dáta 2"
        }
    
        // Môže spracovať výnimku pre konkrétnu async
        try {
            println("Výsledok 1: ${data1.await()}")
        } catch (e: Exception) {
            println("Chyba pri načítaní dát 1: ${e.message}")
        }
        println("Výsledok 2: ${data2.await()}")
    }
    

    Používa sa pre nezávislé dcérske úlohy, kde chyba jednej nemá ovplyvniť ostatné. Nezamení try...catch alebo CoroutineExceptionHandler, ale mení správanie šírenia výnimiek.

  • Šírenie výnimiek v štruktúrovanej konkurencii. Podľa predvolenej konfigurácie, výnimka v dcérskej korutíne zruší rodičovskú korutínu a všetkých jej súrodencov.

    // Príklad šírenia výnimky
    runBlocking {
        val job = launch {
            launch { // Dcérska korutína 1
                delay(100)
                throw Exception("Chyba v dcérskej 1")
            }
            launch { // Dcérska korutína 2
                delay(200)
                println("Dcérska 2 skončila")
            }
        }
        try {
            job.join()
        } catch (e: Exception) {
            println("Zachytená výnimka v rodičovi: $e")
        }
    }
    

    Toto je základné správanie štruktúrovanej konkurencie, ktoré pomáha predchádzať únikom zdrojov a stavov.

  • Použitie async s await(). Výnimky, vyhodené v async, ne sa automaticky šíria. Sú uložené vo vnútri Deferred a vyhadzujú sa iba pri volaní await().

    // Spracovanie výnimiek s async/await
    suspend fun safeAsyncCall() = coroutineScope {
        val deferred = async {
            throw Exception("Chyba v async")
            "Výsledok async"
        }
    
        try {
            val result = deferred.await()
            println("Výsledok: $result")
        } catch (e: Exception) {
            println("Zachytená výnimka z async: ${e.message}")
        }
    }
    

    To umožňuje selektívne spracovanie chýb pre každú asynchrónnu úlohu.

Spôsob Účel Spracováva nechytené? Mení šírenie?
try...catch Spracovanie výnimiek v aktuálnej korutine Nie Nie
CoroutineExceptionHandler Zachytáva neopracované výnimky v Scope Áno Nie
SupervisorJob/Scope Zmena správania šírenia výnimiek Nie Áno
Štruktúrovaná konkurencia Automatické zrušenie pri chybe Áno Áno
async + await() Odložené šírenie výnimky Nie Áno (do await)