0Pricing
Kotlin Academy · Leçon

withTimeout et withTimeoutOrNull

Limitez la durée d’exécution avec des enveloppes de délai d’expiration et gérez TimeoutCancellationException.

withTimeout et withTimeoutOrNull est une leçon Kotlin Academy gratuite sur CoddyKit. Ceci est la leçon 2 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.

Pourquoi utiliser des délais d'expiration ?

Les coroutines peuvent rester bloquées indéfiniment lors d'opérations réseau ou d'E/S. withTimeout annule le bloc s'il ne s'achève pas dans le nombre de millisecondes indiqué.

import kotlinx.coroutines.*
fun main() = runBlocking {
    try {
        withTimeout(200) {
            delay(1000)  // simulates slow network
            println("This never prints")
        }
    } catch (e: TimeoutCancellationException) {
        println("Timed out!")
    }
}

Bases de withTimeout

withTimeout(millis) { ... } lève TimeoutCancellationException (une sous-classe de CancellationException) si le bloc dépasse la limite.

import kotlinx.coroutines.*
suspend fun fetchData(): String {
    delay(100)
    return "data"
}
fun main() = runBlocking {
    val result = withTimeout(500) {
        fetchData()
    }
    println(result) // data
}

withTimeoutOrNull

withTimeoutOrNull renvoie null en cas de dépassement du délai au lieu de lever une exception, ce qui facilite la gestion des délais d'expiration comme un déroulement normal.

import kotlinx.coroutines.*
fun main() = runBlocking {
    val result: String? = withTimeoutOrNull(200) {
        delay(1000)
        "done"
    }
    println(result ?: "Timeout — using default")
}

Délai d'expiration avec valeur de retour

Les deux fonctions renvoient la valeur de la dernière expression du bloc en cas de réussite.

import kotlinx.coroutines.*
fun main() = runBlocking {
    val response = withTimeoutOrNull(500) {
        delay(100)
        mapOf("status" to 200, "body" to "OK")
    }
    println(response?.get("status")) // 200
}

Imbrication des délais d'expiration

Les délais internes expirent d'abord. Le délai externe ne se déclenche que si le délai interne n'annule pas l'exécution en premier — ce qui est utile pour distinguer les délais par requête des délais globaux.

import kotlinx.coroutines.*
fun main() = runBlocking {
    withTimeoutOrNull(1000) {       // global
        withTimeoutOrNull(200) {    // per-call
            delay(300)
            println("inner done")  // won't print
        } ?: println("Inner timed out")
        delay(100)
        println("outer still running")
    }
}

TimeoutCancellationException

TimeoutCancellationException est une CancellationException ; elle est donc traitée comme une annulation normale par les mécanismes des coroutines et ne se propage pas à la portée parente.

import kotlinx.coroutines.*
fun main() = runBlocking {
    val job = launch {
        try {
            withTimeout(100) { delay(1000) }
        } catch (e: TimeoutCancellationException) {
            println("Caught in child: ${e.message}")
        }
    }
    job.join()
    println("Parent still running: ${isActive}")
}

Nettoyage des ressources après un délai d'expiration

Utilisez finally dans withTimeout pour libérer les ressources même lorsque le temps est écoulé.

import kotlinx.coroutines.*
fun main() = runBlocking {
    val result = withTimeoutOrNull(150) {
        try {
            println("Opening resource")
            delay(300)
            "result"
        } finally {
            println("Closing resource") // always runs
        }
    }
    println("Result: $result")
}

Nouvelle tentative avec délai d'expiration

Combinez le délai d'expiration avec une logique de nouvelle tentative : tentez une opération avec un délai par tentative, puis recommencez si le résultat est nul.

import kotlinx.coroutines.*
suspend fun tryFetch(attempt: Int): String? = withTimeoutOrNull(200) {
    delay(if (attempt < 3) 300L else 100L) // fails first 2 attempts
    "success on attempt $attempt"
}
fun main() = runBlocking {
    var result: String? = null
    var attempt = 1
    while (result == null) {
        result = tryFetch(attempt++)
    }
    println(result)
}

withTimeout dans un ViewModel

Dans les ViewModels Android, enveloppez les appels au dépôt avec withTimeoutOrNull dans viewModelScope.launch afin d'afficher un état d'erreur lorsque les réponses sont lentes.

import kotlinx.coroutines.*
// Pseudocode pattern:
suspend fun loadUser(): String = withTimeoutOrNull(3000) {
    // repo.getUser()
    delay(100)
    "Alice"
} ?: "Timeout — using cached data"
fun main() = runBlocking { println(loadUser()) }

Précaution concernant la précision

withTimeout dépend du répartiteur de coroutines. Dans les essais utilisant TestCoroutineScheduler, le temps est virtuel et peut être avancé manuellement.

import kotlinx.coroutines.*
// In unit tests with runTest:
// runTest {
//     withTimeout(1000) {
//         delay(999)  // virtual time — completes instantly
//         println("done")
//     }
// }
fun main() = runBlocking {
    println("Use runTest for virtual-time timeout testing")
}

Choisir entre les deux

Utilisez withTimeout lorsque le dépassement du délai constitue une erreur. Utilisez withTimeoutOrNull lorsqu'il s'agit d'un résultat attendu (par ex. absence du cache, préchargement facultatif).

import kotlinx.coroutines.*
fun main() = runBlocking {
    // Mandatory: throw on timeout
    // withTimeout(500) { criticalOp() }

    // Optional: null on timeout
    val cached = withTimeoutOrNull(50) {
        delay(200); "fresh"
    } ?: "stale"
    println(cached)
}

Vérification rapide

Que renvoie withTimeoutOrNull lorsque le bloc dépasse la limite de temps ?

Récapitulatif

withTimeout lève une exception en cas de dépassement du délai ; withTimeoutOrNull renvoie une valeur nulle. Les deux annulent le bloc de manière coopérative et exécutent les blocs finally. Utilisez finally pour le nettoyage des ressources et withTimeoutOrNull lorsque le dépassement du délai constitue un résultat attendu.

Questions Fréquemment Posées

La leçon « withTimeout et withTimeoutOrNull » est-elle gratuite ?

Oui — le texte complet de « withTimeout et withTimeoutOrNull » 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 « withTimeout et withTimeoutOrNull » ?

Limitez la durée d’exécution avec des enveloppes de délai d’expiration et gérez TimeoutCancellationException. 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 2 sur 4.

Combien de temps prend la leçon « withTimeout et withTimeoutOrNull » ?

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. Annulation coopérative : isActive et ensureActive
  2. withTimeout et withTimeoutOrNull
  3. Nettoyage avec finally et NonCancellable
  4. Propagation de l’annulation dans les hiérarchies de coroutines
← Retour à Kotlin Academy