Sobes.tech
Middle

Co víte o zpracování chyb ve Flow?

sobes.tech AI

Odpověď od AI

Flow v Kotlin Coroutines poskytuje několik způsobů, jak zachytit chyby:

  1. Operátor catch: Zachytává výjimky v stoupajícím toku a umožňuje provést akci (například logování, vrácení záložních dat) nebo nahradit tok.

    flow {
        emit(1)
        throw RuntimeException("Došlo k chybě")
    }.catch { e: Throwable ->
        // Zpracování chyby
        emit(-1) // Vyhození jiné hodnoty při chybě
    }.collect { value ->
        // Zpracování hodnot
    }
    
  2. Blok try-catch: Klasický způsob zpracování výjimek kolem části kódu, včetně sběru Flow.

    try {
        flow {
            emit(1)
            throw RuntimeException("Došlo k chybě")
        }.collect { value ->
            // Zpracování hodnot
        }
    } catch (e: Throwable) {
        // Zpracování chyby
    }
    

    Tento způsob zachytává chyby, které nastanou při sběru Flow, ale nikoli chyby, které jsou způsobeny samotným emitentem Flow před sběrem.

  3. Operátor onEach s try-catch: Pokud je potřeba zpracovat chyby pro každý prvek zvlášť.

    flow {
        emit(1)
        emit(2)
        throw RuntimeException("Chyba po 2")
        emit(3)
    }.onEach { value ->
        try {
            // Zpracování každého prvku
            if (value == 2) throw IllegalArgumentException("Neplatná hodnota 2")
        } catch (e: Throwable) {
            // Zpracování chyby pro konkrétní hodnotu
            println("Chyba pro hodnotu $value: ${e.message}")
            // Můžete znovu vyhodit výjimku, pokud chcete zastavit tok
            throw e
        }
    }.catch { e: Throwable ->
        // Zpracování chyb, které nebyly zachyceny v onEach, nebo chyb, které byly vyhozeny po onEach
        println("Konečná chyba: ${e.message}")
    }.collect { value ->
        println("Sesbíraná hodnota: $value")
    }
    
  4. Operátor retry / retryWhen: Umožňují opakovat zdroj Flow při výskytu chyby.

    • retry: jednoduše opakuje pokus stanovený početkrát.
    • retryWhen: umožňuje určit podmínku pro opakování.
    var attempt = 0
    flow {
        println("Pokus ${++attempt}")
        if (attempt < 3) throw RuntimeException("Opakovaná snaha")
        emit(10)
    }.retryWhen { cause, attempt ->
        // Logika pro určení, zda opakovat
        cause is RuntimeException && attempt < 3
    }.collect { value ->
        println("Úspěch: $value")
    }
    
  5. Předávání výjimek: Chyby, které nejsou výslovně zachyceny, budou předány vzhůru po řetězci Flow a mohou být zachyceny v bloku try-catch kolem sběrače Flow nebo operátorem catch.

Je důležité pochopit, že operátor catch zachytává chyby v stoupajícím toku (upstream). Chyby, které vznikají v klesajícím toku (downstream) po catch, nejsou zachyceny. Pro zpracování takových chyb je třeba použít jiný catch níže v řetězci nebo try-catch kolem sběrače.

Obecné doporučení: umisťujte zpracování chyb co nejblíže ke zdroji chyby, pokud je to možné, ale mějte na paměti, že catch zachytává pouze stoupající tok.