¿Qué formas de manejo de errores en corutinas conoces?
sobes.tech AI
Respuesta de la IA
-
Uso de bloques
try...catch. Método estándar para manejar excepciones. Funciona dentro de una coroutine.// Uso de try-catch suspend fun fetchData(): String { return try { // Operación que puede lanzar una excepción throw Exception("Error al cargar datos") "Datos cargados con éxito" } catch (e: Exception) { "Error: ${e.message}" } }try...catchno es adecuado para manejar excepciones no capturadas lanzadas desde coroutines hijas, ejecutadas en otroCoroutineScope. -
CoroutineExceptionHandler. Captura excepciones no manejadas lanzadas por coroutines que se ejecutan en esteCoroutineScopeo en susCoroutineScopehijos.// CoroutineExceptionHandler val handler = CoroutineExceptionHandler { _, exception -> println("Excepción capturada: $exception") } // Uso de CoroutineExceptionHandler GlobalScope.launch(handler) { // Coroutine que puede lanzar una excepción throw Exception("Error en la coroutine") }CoroutineExceptionHandlersolo se activa para excepciones no manejadas por el mecanismo de concurrencia estructurada. -
SupervisorJobysupervisorScope. A diferencia de unJobnormal, cuando una coroutine hija con error causa la cancelación delJobpadre,SupervisorJobno cancela elJobpadre ante un error en una coroutine hija.supervisorScopecrea unCoroutineScopecon unSupervisorJob.// Uso de supervisorScope suspend fun loadMultipleData() = supervisorScope { val data1 = async { // Puede lanzar una excepción throw Exception("Error en datos 1") "Datos 1" } val data2 = async { "Datos 2" } // Se puede manejar la excepción de una async específica try { println("Resultado 1: ${data1.await()}") } catch (e: Exception) { println("Error al cargar datos 1: ${e.message}") } println("Resultado 2: ${data2.await()}") }Se usa para tareas hijas independientes, donde el error de una no debe afectar a las otras. No reemplaza a
try...catchoCoroutineExceptionHandler, sino que cambia el comportamiento en la propagación de excepciones. -
Propagación de excepciones en concurrencia estructurada. Por defecto, una excepción en una coroutine hija cancela la coroutine padre y a todos sus hermanos.
// Ejemplo de propagación de excepción runBlocking { val job = launch { launch { // Coroutine hija 1 delay(100) throw Exception("Error en la hija 1") } launch { // Coroutine hija 2 delay(200) println("Hija 2 completada") } } try { job.join() } catch (e: Exception) { println("Excepción capturada en la padre: $e") } }Este comportamiento básico de la concurrencia estructurada ayuda a evitar fugas de recursos y estados.
-
Uso de
asyncconawait(). Las excepciones lanzadas enasyncno se propagan automáticamente. Se almacenan enDeferredy se lanzan solo al llamar aawait().// Manejo de excepciones con async/await suspend fun safeAsyncCall() = coroutineScope { val deferred = async { throw Exception("Error en async") "Resultado de async" } try { val result = deferred.await() println("Resultado: $result") } catch (e: Exception) { println("Excepción capturada desde async: ${e.message}") } }Esto permite manejar errores de forma selectiva en cada tarea asíncrona.
| Método | Propósito | ¿Maneja uncaught? | ¿Cambia la propagación? |
|---|---|---|---|
try...catch |
Manejo de excepciones en la coroutine actual | No | No |
CoroutineExceptionHandler |
Captura excepciones no manejadas en Scope | Sí | No |
SupervisorJob/Scope |
Cambia comportamiento en la propagación de excepciones | No | Sí |
| Concurrencia estructurada | Cancelación automática en error | Sí | Sí |
async + await() |
Propagación diferida de excepciones | No | Sí (antes de await) |