Sobes.tech
Middle

Quelles méthodes de gestion des erreurs dans les coroutines connaissez-vous?

sobes.tech IA

Réponse de l'IA

  • Utilisation des blocs try...catch. Méthode standard pour gérer les exceptions. Fonctionne à l'intérieur d'une coroutine.

    // Utilisation de try-catch
    suspend fun fetchData(): String {
        return try {
            // Opération pouvant lancer une exception
            throw Exception("Erreur lors du chargement des données")
            "Données chargées avec succès"
        } catch (e: Exception) {
            "Erreur: ${e.message}"
        }
    }
    

    try...catch n'est pas adapté pour gérer les exceptions non attrapées lancées par des coroutines enfants, exécutées dans un autre CoroutineScope.

  • CoroutineExceptionHandler. Intercepte les exceptions non gérées lancées par des coroutines qui s'exécutent dans ce CoroutineScope ou ses CoroutineScope enfants.

    // CoroutineExceptionHandler
    val handler = CoroutineExceptionHandler { _, exception ->
        println("Exception interceptée: $exception")
    }
    
    // Utilisation de CoroutineExceptionHandler
    GlobalScope.launch(handler) {
        // Coroutine pouvant lancer une exception
        throw Exception("Erreur dans la coroutine")
    }
    

    CoroutineExceptionHandler ne s'active que pour les exceptions non gérées par le mécanisme de concurrence structurée.

  • SupervisorJob et supervisorScope. Contrairement à un Job classique, lorsqu'une coroutine fille avec erreur entraîne l'annulation du Job parent, SupervisorJob ne l'annule pas. supervisorScope crée un CoroutineScope avec un SupervisorJob.

    // Utilisation de supervisorScope
    suspend fun loadMultipleData() = supervisorScope {
        val data1 = async {
            // Peut lancer une exception
            throw Exception("Erreur dans données 1")
            "Données 1"
        }
        val data2 = async {
            "Données 2"
        }
    
        // Peut gérer l'exception pour une async spécifique
        try {
            println("Résultat 1: ${data1.await()}")
        } catch (e: Exception) {
            println("Erreur lors du chargement des données 1: ${e.message}")
        }
        println("Résultat 2: ${data2.await()}")
    }
    

    Utilisé pour des tâches enfants indépendantes, où l'erreur d'une ne doit pas affecter les autres. Ne remplace pas try...catch ou CoroutineExceptionHandler, mais modifie le comportement de propagation des exceptions.

  • Propagation des exceptions en concurrence structurée. Par défaut, une exception dans une coroutine enfant annule la coroutine parent et tous ses frères.

    // Exemple de propagation d'exception
    runBlocking {
        val job = launch {
            launch { // Coroutine enfant 1
                delay(100)
                throw Exception("Erreur dans l'enfant 1")
            }
            launch { // Coroutine enfant 2
                delay(200)
                println("Enfant 2 terminée")
            }
        }
        try {
            job.join()
        } catch (e: Exception) {
            println("Exception interceptée dans le parent: $e")
        }
    }
    

    C'est le comportement de base de la concurrence structurée, qui aide à éviter les fuites de ressources et d'états.

  • Utilisation de async avec await(). Les exceptions lancées dans async ne se propagent pas automatiquement. Elles sont stockées dans Deferred et ne sont levées qu'au moment de l'appel à await().

    // Gestion des exceptions avec async/await
    suspend fun safeAsyncCall() = coroutineScope {
        val deferred = async {
            throw Exception("Erreur dans async")
            "Résultat de async"
        }
    
        try {
            val result = deferred.await()
            println("Résultat: $result")
        } catch (e: Exception) {
            println("Exception interceptée depuis async: ${e.message}")
        }
    }
    

    Cela permet de gérer sélectivement les erreurs pour chaque tâche asynchrone.

Méthode Objectif Gère les uncaught? Change la propagation?
try...catch Gestion des exceptions dans la coroutine courante Non Non
CoroutineExceptionHandler Capture des exceptions non gérées dans Scope Oui Non
SupervisorJob/Scope Modifie le comportement de propagation des exceptions Non Oui
Concurrence structurée Annulation automatique en cas d'erreur Oui Oui
async + await() Propagation différée des exceptions Non Oui (avant await)