Sobes.tech
Middle

Ce știi despre gestionarea erorilor în Flow?

sobes.tech AI

Răspuns de la AI

Flow în Kotlin Coroutines oferă mai multe modalități de gestionare a erorilor:

  1. Operatorul catch: Interceptează excepțiile din fluxul ascendent și permite executarea unei acțiuni (de exemplu, înregistrare, returnare de date de rezervă) sau înlocuirea fluxului.

    flow {
        emit(1)
        throw RuntimeException("A apărut o eroare")
    }.catch { e: Throwable ->
        // Gestionarea erorii
        emit(-1) // Emiterea unei alte valori în caz de eroare
    }.collect { value ->
        // Procesarea valorilor
    }
    
  2. Blocul try-catch: Mod clasic de a trata excepțiile în jurul unei secțiuni de cod, inclusiv colectarea Flow.

    try {
        flow {
            emit(1)
            throw RuntimeException("A apărut o eroare")
        }.collect { value ->
            // Procesarea valorilor
        }
    } catch (e: Throwable) {
        // Gestionarea erorii
    }
    

    Acest mod capturează erorile care apar în timpul colectării Flow, dar nu erorile produse de emițătorul Flow înainte de colectare.

  3. Operatorul onEach cu try-catch: Dacă doriți să tratați erorile pentru fiecare element separat.

    flow {
        emit(1)
        emit(2)
        throw RuntimeException("Eroare după 2")
        emit(3)
    }.onEach { value ->
        try {
            // Procesarea fiecărui element
            if (value == 2) throw IllegalArgumentException("Valoare invalidă 2")
        } catch (e: Throwable) {
            // Gestionarea erorii pentru o valoare specifică
            println("Eroare pentru valoarea $value: ${e.message}")
            // Se poate arunca excepția mai departe pentru a opri fluxul
            throw e
        }
    }.catch { e: Throwable ->
        // Gestionarea erorilor nepreluate în onEach sau erorilor aruncate după onEach
        println("Eroare finală: ${e.message}")
    }.collect { value ->
        println("Valoare colectată: $value")
    }
    
  4. Operatorul retry / retryWhen: Permite reluarea încercării sursei Flow în cazul unei erori.

    • retry: Repetă pur și simplu încercarea de un număr specificat de ori.
    • retryWhen: Permite definirea unei condiții pentru reluare.
    var attempt = 0
    flow {
        println("Încercarea ${++attempt}")
        if (attempt < 3) throw RuntimeException("Repetare")
        emit(10)
    }.retryWhen { cause, attempt ->
        // Logica pentru determinarea dacă trebuie reluat
        cause is RuntimeException && attempt < 3
    }.collect { value ->
        println("Succes: $value")
    }
    
  5. Transmiterea excepțiilor: Erorile nepreluate explicit vor fi propagate în sus pe lanțul Flow și pot fi capturate într-un bloc try-catch în jurul colectorului Flow sau cu operatorul catch.

Este important să înțelegeți că operatorul catch capturează erorile din fluxul ascendent (upstream). Erorile care apar în fluxul descendent (downstream) după catch nu sunt capturate. Pentru a gestiona astfel de erori, trebuie să folosiți un alt catch mai jos în lanț sau un try-catch în jurul colectorului.

Recomandarea generală: plasați gestionarea erorilor cât mai aproape de sursa erorii, dacă este posibil, dar țineți cont că catch gestionează doar fluxul ascendent.