Sobes.tech
Middle

Welke manieren van foutafhandeling in coroutines ken je?

sobes.tech AI

Antwoord van AI

  • Gebruik van try...catch blokken. Standaardmethode voor foutafhandeling. Werkt binnen een coroutine.

    // Toepassing van try-catch
    suspend fun fetchData(): String {
        return try {
            // Operatie die een uitzondering kan veroorzaken
            throw Exception("Fout bij het laden van gegevens")
            "Gegevens succesvol geladen"
        } catch (e: Exception) {
            "Fout: ${e.message}"
        }
    }
    

    try...catch is niet geschikt voor het afhandelen van uncaught uitzonderingen die worden gegooid uit child coroutines die in een andere CoroutineScope worden uitgevoerd.

  • CoroutineExceptionHandler. Vangt onverwerkte uitzonderingen op die door coroutines worden gegooid, die in deze CoroutineScope of in zijn child CoroutineScope worden gestart.

    // CoroutineExceptionHandler
    val handler = CoroutineExceptionHandler { _, exception ->
        println("Vangst exception: $exception")
    }
    
    // Toepassing van CoroutineExceptionHandler
    GlobalScope.launch(handler) {
        // Coroutine die een uitzondering kan gooien
        throw Exception("Fout in coroutine")
    }
    

    CoroutineExceptionHandler wordt alleen geactiveerd voor uitzonderingen die niet worden afgehandeld door het gestructureerde concurrency mechanisme.

  • SupervisorJob en supervisorScope. In tegenstelling tot een gewoon Job, wanneer een child coroutine een fout veroorzaakt, leidt dit niet tot het annuleren van de parent Job. supervisorScope creëert een CoroutineScope met een SupervisorJob.

    // Gebruik van supervisorScope
    suspend fun loadMultipleData() = supervisorScope {
        val data1 = async {
            // Kan een uitzondering veroorzaken
            throw Exception("Fout in data 1")
            "Data 1"
        }
        val data2 = async {
            "Data 2"
        }
    
        // Foutafhandeling voor een specifieke async
        try {
            println("Resultaat 1: ${data1.await()}")
        } catch (e: Exception) {
            println("Fout bij laden data 1: ${e.message}")
        }
        println("Resultaat 2: ${data2.await()}")
    }
    

    Wordt gebruikt voor onafhankelijke child taken, waarbij de fout van de ene niet de andere mag beïnvloeden. Vervangt niet try...catch of CoroutineExceptionHandler, maar verandert het gedrag van het verspreiden van uitzonderingen.

  • Verspreiding van uitzonderingen in gestructureerde concurrency. Standaard, een uitzondering in een child coroutine annuleert de parent coroutine en al haar siblings.

    // Voorbeeld van verspreiding van een uitzondering
    runBlocking {
        val job = launch {
            launch { // Child coroutine 1
                delay(100)
                throw Exception("Fout in child 1")
            }
            launch { // Child coroutine 2
                delay(200)
                println("Child 2 voltooid")
            }
        }
        try {
            job.join()
        } catch (e: Exception) {
            println("Exception opgevangen in parent: $e")
        }
    }
    

    Dit is het basisgedrag van gestructureerde concurrency, dat helpt resource leaks en toestand te voorkomen.

  • Gebruik van async met await(). Uitzonderingen die in async worden gegooid, worden niet automatisch verspreid. Ze worden opgeslagen binnen Deferred en worden alleen gegooid bij het aanroepen van await().

    // Afhandeling van uitzonderingen met async/await
    suspend fun safeAsyncCall() = coroutineScope {
        val deferred = async {
            throw Exception("Fout in async")
            "Async resultaat"
        }
    
        try {
            val result = deferred.await()
            println("Resultaat: $result")
        } catch (e: Exception) {
            println("Vangst exception uit async: ${e.message}")
        }
    }
    

    Dit maakt het mogelijk om fouten selectief te verwerken voor elke asynchrone taak.

Methode Doel Vangt uncaught? Verandert verspreiding?
try...catch Afhandeling van uitzonderingen binnen huidige coroutine Nee Nee
CoroutineExceptionHandler Vangt onverwerkte uitzonderingen in Scope Ja Nee
SupervisorJob/Scope Verandert gedrag van verspreiding van uitzonderingen Nee Ja
Gestructureerde concurrency Automatische annulering bij fout Ja Ja
async + await() Uitgestelde verspreiding van uitzonderingen Nee Ja (voor await)