0Pricing
Kotlin Academy · Leçon

SupervisorJob ou Job : isolation des échecs

Utilisez SupervisorJob pour empêcher l’échec d’un enfant d’annuler ses frères et sœurs.

SupervisorJob ou Job : isolation des échecs est une leçon Kotlin Academy gratuite sur CoddyKit. Ceci est la leçon 1 sur 4. Tu peux lire la leçon complète ci-dessous gratuitement — puis la pratiquer en direct dans le navigateur avec un éditeur de code intégré et un tuteur IA 24/7. Elle fait partie du parcours d'apprentissage Kotlin Academy, et ta progression se synchronise sur le web et l'application CoddyKit. Le cours Kotlin Academy comprend 4 leçons au total.

Propagation par défaut des échecs de Job

Avec un Job standard, l'échec d'un enfant annule le parent, qui annule à son tour tous les frères. Un seul échec fait tomber toute la hiérarchie.

import kotlinx.coroutines.*
fun main() = runBlocking {
    try {
        coroutineScope {
            launch { delay(50); throw RuntimeException("child 1 failed") }
            launch { delay(1000); println("child 2 — never prints") }
        }
    } catch (e: RuntimeException) {
        println("Caught: ${e.message}")
    }
}

Présentation de SupervisorJob

SupervisorJob modifie cette règle : l'échec d'un enfant n'annule ni les frères ni le parent (NOT). Chaque enfant échoue indépendamment.

import kotlinx.coroutines.*
fun main() = runBlocking {
    val supervisor = SupervisorJob()
    val scope = CoroutineScope(coroutineContext + supervisor)
    scope.launch { throw RuntimeException("child 1 failed") }
    scope.launch { delay(100); println("child 2 still runs") }
    delay(200)
    supervisor.cancel()
}

Générateur supervisorScope

supervisorScope { } crée une portée dont le parent est un SupervisorJob. C'est la manière idiomatique d'exécuter des enfants indépendants.

import kotlinx.coroutines.*
fun main() = runBlocking {
    supervisorScope {
        val job1 = launch {
            throw RuntimeException("job1 failed")
        }
        val job2 = launch {
            delay(100)
            println("job2 succeeded")
        }
        job1.join()  // wait for job1 (it failed)
        job2.join()  // job2 is unaffected
    }
}

Intercepter les échecs des enfants

Avec supervisorScope, chaque enfant gère sa propre exception. Les exceptions non gérées des enfants doivent être interceptées pour chaque enfant.

import kotlinx.coroutines.*
fun main() = runBlocking {
    supervisorScope {
        val result = async {
            delay(50)
            throw RuntimeException("async failed")
        }
        try {
            result.await()
        } catch (e: RuntimeException) {
            println("Caught from async: ${e.message}")
        }
        println("Scope continues")
    }
}

Job ou SupervisorJob lors de la création d'une portée

Transmettez SupervisorJob() lors de la création d'un CoroutineScope pour un service ou un ViewModel qui doit survivre aux échecs individuels de ses enfants.

import kotlinx.coroutines.*
class MyService {
    private val scope = CoroutineScope(Dispatchers.Default + SupervisorJob())
    fun startTask(name: String) {
        scope.launch {
            if (name == "fail") throw RuntimeException("$name failed")
            println("$name done")
        }
    }
    fun stop() = scope.cancel()
}
fun main() = runBlocking {
    val svc = MyService()
    svc.startTask("fail")
    svc.startTask("ok")
    delay(100)
    svc.stop()
}

viewModelScope utilise SupervisorJob

Le viewModelScope d'Android repose sur un SupervisorJob. Un lancement qui échoue n'annule pas les autres coroutines du ViewModel.

import kotlinx.coroutines.*
// Android ViewModel internals:
// val viewModelScope = CoroutineScope(SupervisorJob() + Dispatchers.Main.immediate)
// Each launch is independent — one failure doesn't crash the ViewModel
fun main() = runBlocking {
    println("viewModelScope = SupervisorJob + Main")
}

Décomposition parallèle avec supervisorScope

Utilisez supervisorScope + async pour les tâches parallèles dont certaines peuvent échouer sans affecter les autres.

import kotlinx.coroutines.*
fun main() = runBlocking {
    val results = supervisorScope {
        val a = async { delay(50); "result-A" }
        val b = async { throw RuntimeException("B failed") }
        val c = async { delay(30); "result-C" }
        listOf(
            runCatching { a.await() },
            runCatching { b.await() },
            runCatching { c.await() }
        )
    }
    results.forEach { println(it) }
}

Quand utiliser une tâche ordinaire

Utilisez une Job ordinaire (coroutineScope) lorsque tous les enfants doivent réussir ensemble : l'échec de l'un doit interrompre le groupe. Comme pour une transaction : tout ou rien.

import kotlinx.coroutines.*
fun main() = runBlocking {
    try {
        coroutineScope {  // regular Job
            val a = async { delay(50); "A" }
            val b = async { throw RuntimeException("B failed") }
            println(a.await())
            println(b.await())  // throws — cancels a too
        }
    } catch (e: RuntimeException) {
        println("Transaction failed: ${e.message}")
    }
}

Propagation des exceptions dans une portée de supervision

Dans supervisorScope, une exception ne se propage à la portée que si elle s'échappe du niveau supérieur de l'enfant, c'est-à-dire si l'enfant ne l'intercepte pas. Le parent ne la reçoit pas.

import kotlinx.coroutines.*
fun main() = runBlocking {
    supervisorScope {
        // Exception caught inside child — scope unaffected
        launch {
            try { throw RuntimeException("handled") }
            catch (e: Exception) { println("Child caught: ${e.message}") }
        }
        delay(100)
        println("Scope survived")
    }
}

CoroutineExceptionHandler avec SupervisorJob

Installez un CoroutineExceptionHandler dans une portée de supervision pour journaliser les échecs non interceptés des enfants ou y réagir sans faire planter la portée.

import kotlinx.coroutines.*
fun main() = runBlocking {
    val handler = CoroutineExceptionHandler { _, e ->
        println("Uncaught: ${e.message}")
    }
    val scope = CoroutineScope(SupervisorJob() + handler)
    scope.launch { throw RuntimeException("unhandled failure") }
    scope.launch { delay(100); println("still running") }
    delay(200)
    scope.cancel()
}

Résumé de l'isolation des échecs

Tâche : l'échec d'un enfant entraîne celui de tous les autres. SupervisorJob : les enfants échouent indépendamment. Utilisez la supervision pour les services et les ViewModels, et une tâche ordinaire pour les groupes transactionnels.

import kotlinx.coroutines.*
// Decision table:
// coroutineScope { }   -> Job: all-or-nothing
// supervisorScope { }  -> SupervisorJob: independent failures
// CoroutineScope(SupervisorJob()) -> long-lived service
fun main() = runBlocking { println("Pick the right job for the right scope") }

Vérification rapide

Quelle portée empêche l'échec d'un enfant d'annuler ses frères ?

Récapitulatif

Tâche : l'échec se propage aux frères. SupervisorJob/supervisorScope : les échecs sont isolés pour chaque enfant. Utilisez supervisorScope pour les tâches parallèles indépendantes, et coroutineScope pour les groupes transactionnels.

Questions Fréquemment Posées

La leçon « SupervisorJob ou Job : isolation des échecs » est-elle gratuite ?

Oui — le texte complet de « SupervisorJob ou Job : isolation des échecs » est gratuit à lire ici sur le web. Pour la pratiquer de manière interactive (un éditeur de code intégré et un tuteur IA 24/7) et déverrouiller le reste du cours Kotlin Academy, passe à CoddyKit PRO. Le cours Kotlin Academy comprend 4 leçons au total.

Qu'est-ce que j'apprendrai dans « SupervisorJob ou Job : isolation des échecs » ?

Utilisez SupervisorJob pour empêcher l’échec d’un enfant d’annuler ses frères et sœurs. Tu pratiques Kotlin Academy avec du code pratique que tu exécutes directement dans le navigateur, et un tuteur IA 24/7 répond à tes questions au fur et à mesure que tu avances dans la leçon.

Dois-je avoir de l'expérience pour commencer Kotlin Academy ?

Aucune expérience préalable n'est requise. Kotlin Academy sur CoddyKit est structuré pour les débutants jusqu'aux apprenants avancés, donc tu peux commencer ici ou depuis le début et avancer à ton rythme. Ceci est la leçon 1 sur 4.

Combien de temps prend la leçon « SupervisorJob ou Job : isolation des échecs » ?

La plupart des leçons CoddyKit prennent environ 5–10 minutes. Chacune est courte et interactive, tu progresses régulièrement et tu repiques exactement où tu t'es arrêté sur le web et l'app.

Peux-tu écrire et exécuter du code dans cette leçon Kotlin Academy ?

Oui. Chaque leçon Kotlin Academy inclut un éditeur de code intégré, tu écris et exécutes du vrai code directement dans ton navigateur et tu reçois des retours IA instantanés — aucune configuration locale requise.

Toutes les leçons de ce cours

  1. SupervisorJob ou Job : isolation des échecs
  2. CoroutineExceptionHandler : gestionnaire global des exceptions non interceptées
  3. Propagation des exceptions avec async/await
  4. Concevoir des architectures de coroutines résilientes
← Retour à Kotlin Academy