Sobes.tech
Middle

Kokius klaidų tvarkymo būdus žinote korutinose?

sobes.tech AI

Atsakymas iš AI

  • Naudojimas try...catch blokų. Standartinis išimčių tvarkymo būdas. Veikia viduje korutinos.

    // Naudojant try-catch
    suspend fun fetchData(): String {
        return try {
            // Operacija, galinti išmesti išimtį
            throw Exception("Krovimo klaida")
            "Duomenys sėkmingai įkelti"
        } catch (e: Exception) {
            "Klaida: ${e.message}"
        }
    }
    

    try...catch netinka nepagautoms išimtims apdoroti, kurias išmeta vaiko korutinos, paleistos kitoje CoroutineScope.

  • CoroutineExceptionHandler. Sugauja neapdorotas išimtis, kurias išmeta korutinos, paleistos šiame CoroutineScope arba jo vaikų CoroutineScope.

    // CoroutineExceptionHandler
    val handler = CoroutineExceptionHandler { _, exception ->
        println("Sugauta išimtis: $exception")
    }
    
    // Naudojant CoroutineExceptionHandler
    GlobalScope.launch(handler) {
        // Korutina, galinti išmesti išimtį
        throw Exception("Klaida korutinoje")
    }
    

    CoroutineExceptionHandler veikia tik neapdorotoms išimtims, kurios nėra tvarkomos struktūrizuotos konkurencijos mechanizmo.

  • SupervisorJob ir supervisorScope. Skirtingai nuo įprasto Job, kai vaiko korutina su klaida sukelia tėvinio Job atšaukimą, SupervisorJob to nepadaro. supervisorScope sukuria CoroutineScope su SupervisorJob.

    // Naudojant supervisorScope
    suspend fun loadMultipleData() = supervisorScope {
        val data1 = async {
            // Galima išmesti išimtį
            throw Exception("Klaida duomenyse 1")
            "Duomenys 1"
        }
        val data2 = async {
            "Duomenys 2"
        }
    
        // Galima apdoroti išimtį konkrečiai `async`
        try {
            println("Rezultatas 1: ${data1.await()}")
        } catch (e: Exception) {
            println("Klaida įkeliant duomenis 1: ${e.message}")
        }
        println("Rezultatas 2: ${data2.await()}")
    }
    

    Naudojama nepriklausomoms vaikų užduotims, kur klaida vienoje neturėtų paveikti kitų. Nenaudoja try...catch ar CoroutineExceptionHandler, o keičia išimčių plitimo elgesį.

  • Išimčių plitimas struktūrizuotoje konkurencijoje. Pagal numatytuosius nustatymus, vaiko korutinos išimtis atšaukia tėvinę korutiną ir visus jos broliais.

    // Pavyzdys, kaip plinta išimtis
    runBlocking {
        val job = launch {
            launch { // Vaiko korutina 1
                delay(100)
                throw Exception("Klaida vaiko 1")
            }
            launch { // Vaiko korutina 2
                delay(200)
                println("Vaiko 2 įvykdyta")
            }
        }
        try {
            job.join()
        } catch (e: Exception) {
            println("Išimtis sugauta tėvinėje: $e")
        }
    }
    

    Tai yra pagrindinis struktūrizuotos konkurencijos elgesys, padedantis išvengti išteklių ir būsenų nutekėjimo.

  • Naudojant async su await(). Išimtis, išmesta async, _ne_plinta automatiškai. Ji saugoma Deferred ir išmetama tik iškvietus await().

    // Išimčių apdorojimas su async/await
    suspend fun safeAsyncCall() = coroutineScope {
        val deferred = async {
            throw Exception("Klaida async")
            "Async rezultatas"
        }
    
        try {
            val result = deferred.await()
            println("Rezultatas: $result")
        } catch (e: Exception) {
            println("Sugauta išimtis iš async: ${e.message}")
        }
    }
    

    Tai leidžia pasirinktinai apdoroti klaidas kiekvienai asinchroninei užduočiai.

Būdas Paskirtis Ar apdoroja nepagautas? Ar keičia plitimą?
try...catch Išimčių apdorojimas viduje esamos korutinos Ne Ne
CoroutineExceptionHandler Sugauja neapdorotas išimtis Scope'e Taip Ne
SupervisorJob/Scope Keičia išimčių plitimo elgesį Ne Taip
Struktūrizuota konkurencija Automatinis atšaukimas klaidos atveju Taip Taip
async + await() Atidėtas išimčių plitimas Ne Taip (iki await)