Sobes.tech
Middle

¿Qué sabes sobre el manejo de errores en Flow?

sobes.tech AI

Respuesta de la IA

Flow en Kotlin Coroutines ofrece varias formas de manejar errores:

  1. Operador catch: Captura excepciones en el flujo ascendente y permite realizar una acción (por ejemplo, registrar, devolver datos de respaldo) o reemplazar el flujo.

    flow {
        emit(1)
        throw RuntimeException("Ocurrió un error")
    }.catch { e: Throwable ->
        // Manejo del error
        emit(-1) // Emitir otro valor en caso de error
    }.collect { value ->
        // Manejo de valores
    }
    
  2. Bloque try-catch: Método clásico para manejar excepciones alrededor de un bloque de código, incluyendo la recopilación de Flow.

    try {
        flow {
            emit(1)
            throw RuntimeException("Ocurrió un error")
        }.collect { value ->
            // Manejo de valores
        }
    } catch (e: Throwable) {
        // Manejo del error
    }
    

    Este método captura errores que ocurren durante la recopilación de Flow, pero no errores producidos por el emisor de Flow antes de la recopilación.

  3. Operador onEach con try-catch: Si necesitas manejar errores para cada elemento por separado.

    flow {
        emit(1)
        emit(2)
        throw RuntimeException("Error después de 2")
        emit(3)
    }.onEach { value ->
        try {
            // Manejo de cada elemento
            if (value == 2) throw IllegalArgumentException("Valor no válido 2")
        } catch (e: Throwable) {
            // Manejo del error para un valor específico
            println("Error para el valor $value: ${e.message}")
            // Se puede lanzar la excepción para detener el flujo
            throw e
        }
    }.catch { e: Throwable ->
        // Manejo de errores no capturados en onEach, o errores lanzados después de onEach
        println("Error final: ${e.message}")
    }.collect { value ->
        println("Valor recopilado: $value")
    }
    
  4. Operador retry / retryWhen: Permiten reintentar la fuente de Flow en caso de error.

    • retry: Repite simplemente el intento un número determinado de veces.
    • retryWhen: Permite definir una condición para reintentar.
    var attempt = 0
    flow {
        println("Intento ${++attempt}")
        if (attempt < 3) throw RuntimeException("Reintento")
        emit(10)
    }.retryWhen { cause, attempt ->
        // Lógica para determinar si se debe reintentar
        cause is RuntimeException && attempt < 3
    }.collect { value ->
        println("Éxito: $value")
    }
    
  5. Propagación de excepciones: Los errores no capturados explícitamente serán propagados hacia arriba en la cadena de Flow y pueden ser capturados en un bloque try-catch alrededor del recolector de Flow o con el operador catch.

Es importante entender que el operador catch captura errores en el flujo ascendente (upstream). Los errores que ocurren en el flujo descendente (downstream) después de catch no son capturados. Para manejar estos errores, se debe usar otro catch más abajo en la cadena o un try-catch alrededor del recolector.

Recomendación general: colocar el manejo de errores lo más cerca posible de la fuente del error, si es posible, pero tener en cuenta que catch solo maneja el flujo ascendente.