withTimeout y withTimeoutOrNull
Limite el tiempo de ejecución con wrappers de timeout y gestione TimeoutCancellationException.
withTimeout y withTimeoutOrNull es una lección gratuita de Kotlin Academy en CoddyKit. Esta es la lección 2 de 4. Puedes leer la lección completa abajo gratuitamente — luego la practicas en el navegador con un editor de código integrado y un tutor de IA 24/7. Forma parte de la ruta de aprendizaje de Kotlin Academy, y tu progreso se sincroniza en la web y la app de CoddyKit. El curso de Kotlin Academy incluye 4 lecciones en total.
¿Por qué usar tiempos de espera?
Las corrutinas pueden quedar bloqueadas indefinidamente en operaciones de red o de E/S. withTimeout cancela el bloque si no se completa dentro de los milisegundos indicados.
import kotlinx.coroutines.*
fun main() = runBlocking {
try {
withTimeout(200) {
delay(1000) // simulates slow network
println("This never prints")
}
} catch (e: TimeoutCancellationException) {
println("Timed out!")
}
}Conceptos básicos de withTimeout
withTimeout(millis) { ... } lanza TimeoutCancellationException (una subclase de CancellationException) si el bloque supera el límite.
import kotlinx.coroutines.*
suspend fun fetchData(): String {
delay(100)
return "data"
}
fun main() = runBlocking {
val result = withTimeout(500) {
fetchData()
}
println(result) // data
}withTimeoutOrNull
withTimeoutOrNull devuelve null cuando se agota el tiempo, en lugar de lanzar una excepción, lo que facilita gestionar los tiempos de espera como parte del flujo normal.
import kotlinx.coroutines.*
fun main() = runBlocking {
val result: String? = withTimeoutOrNull(200) {
delay(1000)
"done"
}
println(result ?: "Timeout — using default")
}Tiempo de espera con valor de retorno
Ambas funciones devuelven el valor de la última expresión del bloque cuando la operación tiene éxito.
import kotlinx.coroutines.*
fun main() = runBlocking {
val response = withTimeoutOrNull(500) {
delay(100)
mapOf("status" to 200, "body" to "OK")
}
println(response?.get("status")) // 200
}Anidamiento de tiempos de espera
Los tiempos de espera internos se agotan primero. El tiempo de espera externo solo se activa si el interno no cancela antes la operación, lo que resulta útil para distinguir entre tiempos de espera por solicitud y globales.
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 es una CancellationException, por lo que la maquinaria de corrutinas la trata como una cancelación normal y no la propaga al ámbito padre.
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}")
}Limpieza de recursos al agotarse el tiempo
Use finally dentro de withTimeout para liberar los recursos incluso cuando se agote el tiempo.
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")
}Reintento con tiempo de espera
Combine el tiempo de espera con la lógica de reintento: intente realizar una operación con un tiempo de espera por intento y vuelva a intentarlo si el resultado es null.
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 en ViewModel
En los ViewModel de Android, envuelva las llamadas al repositorio con withTimeoutOrNull dentro de viewModelScope.launch para mostrar un estado de error cuando las respuestas sean lentas.
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()) }Advertencia sobre la precisión
withTimeout depende del dispatcher de la corrutina. En las pruebas que utilizan TestCoroutineScheduler, el tiempo es virtual y se puede adelantar manualmente.
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")
}Cómo elegir entre ambos
Use withTimeout cuando el tiempo de espera sea un error. Use withTimeoutOrNull cuando sea un resultado esperado, por ejemplo, si no se encuentra una entrada en la caché o durante una precarga opcional.
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)
}Comprobación rápida
¿Qué devuelve withTimeoutOrNull cuando el bloque supera el límite de tiempo?
Resumen
withTimeout lanza una excepción cuando se agota el tiempo; withTimeoutOrNull devuelve null. Ambas funciones cancelan el bloque de forma cooperativa y ejecutan los bloques finally. Use finally para limpiar recursos y withTimeoutOrNull cuando el tiempo de espera sea un resultado esperado.
Preguntas frecuentes
¿La lección «withTimeout y withTimeoutOrNull» es gratis?
Sí — el texto completo de «withTimeout y withTimeoutOrNull» es gratis para leer aquí en la web. Para practicarla de forma interactiva (editor de código integrado y tutor de IA 24/7) y desbloquear el resto del curso de Kotlin Academy, actualiza a CoddyKit PRO. El curso de Kotlin Academy incluye 4 lecciones en total.
¿Qué aprenderé en «withTimeout y withTimeoutOrNull»?
Limite el tiempo de ejecución con wrappers de timeout y gestione TimeoutCancellationException. Practicas Kotlin Academy con código real que ejecutas directamente en el navegador, y un tutor de IA 24/7 responde tus preguntas mientras trabajas en la lección.
¿Necesito experiencia previa para empezar Kotlin Academy?
No se requiere experiencia previa. Kotlin Academy en CoddyKit está estructurado para principiantes hasta estudiantes avanzados, así que puedes empezar aquí o desde el inicio y avanzar a tu ritmo. Esta es la lección 2 de 4.
¿Cuánto tiempo toma la lección «withTimeout y withTimeoutOrNull»?
La mayoría de las lecciones de CoddyKit toman alrededor de 5–10 minutos. Cada una es compacta e interactiva, así que avanzas constantemente y retomas exactamente por donde dejaste en la web y la app.
¿Puedo escribir y ejecutar código en esta lección de Kotlin Academy?
Sí. Cada lección de Kotlin Academy incluye un editor de código integrado, así que escribes y ejecutas código real directamente en tu navegador y obtienes retroalimentación instantánea de IA — sin configuración local necesaria.
Todas las lecciones de este curso
- Cancelación cooperativa: isActive y ensureActive
- withTimeout y withTimeoutOrNull
- Limpieza con finally y NonCancellable
- Propagación de la cancelación en jerarquías de corrutinas