Sobes.tech
Middle

Ką žinote apie klaidų apdorojimą Flow?

sobes.tech AI

Atsakymas iš AI

Flow Kotlin Coroutines siūlo keletą būdų tvarkyti klaidas:

  1. Operatorius catch: Gaudo išimtis kylantį srautą ir leidžia atlikti veiksmą (pvz., žurnalo įrašymą, atsarginės duomenų grąžinimą) arba pakeisti srautą.

    flow {
        emit(1)
        throw RuntimeException("Įvyko klaida")
    }.catch { e: Throwable ->
        // Klaidos apdorojimas
        emit(-1) // Išleisti kitą reikšmę klaidos atveju
    }.collect { value ->
        // Reikšmių apdorojimas
    }
    
  2. try-catch blokas: Klasikinis būdas apdoroti išimtis aplink kodo dalį, įskaitant Flow surinkimą.

    try {
        flow {
            emit(1)
            throw RuntimeException("Įvyko klaida")
        }.collect { value ->
            // Reikšmių apdorojimas
        }
    } catch (e: Throwable) {
        // Klaidos apdorojimas
    }
    

    Šis būdas gaudo klaidas, kurios įvyksta surenkant Flow, bet ne klaidas, kurias sukelia pats emitentas prieš surinkimą.

  3. onEach operatorius su try-catch: Jei reikia apdoroti klaidas kiekvienam elementui atskirai.

    flow {
        emit(1)
        emit(2)
        throw RuntimeException("Klaida po 2")
        emit(3)
    }.onEach { value ->
        try {
            // Kiekvieno elemento apdorojimas
            if (value == 2) throw IllegalArgumentException("Neleistina reikšmė 2")
        } catch (e: Throwable) {
            // Klaidos apdorojimas konkrečiam value
            println("Klaida reikšmei $value: ${e.message}")
            // Galite išmesti išimtį toliau, jei norite sustabdyti srautą
            throw e
        }
    }.catch { e: Throwable ->
        // Klaidų apdorojimas, kurios nebuvo pagautos onEach arba išmestos po jo
        println("Galutinis klaida: ${e.message}")
    }.collect { value ->
        println("Surinkta reikšmė: $value")
    }
    
  4. retry / retryWhen operatoriai: Leidžia pakartoti šaltinį Flow, jei įvyksta klaida.

    • retry: paprasčiausiai pakartoja bandymą nurodytą kartų skaičių.
    • retryWhen: leidžia nustatyti sąlygą pakartojimui.
    var attempt = 0
    flow {
        println("Bandymas ${++attempt}")
        if (attempt < 3) throw RuntimeException("Pakartotinas bandymas")
        emit(10)
    }.retryWhen { cause, attempt ->
        // Logika, ar reikia pakartoti
        cause is RuntimeException && attempt < 3
    }.collect { value ->
        println("Sėkmė: $value")
    }
    
  5. Išimtis perkelti aukštyn: Nepačiuptos klaidos bus perkelta aukštyn Flow grandinėje ir gali būti pagauta try-catch bloke aplink Flow surinkėją arba catch operatoriu.

Svarbu suprasti, kad catch operatorius gaudo klaidas kylantį srautą (upstream). Klaidos, kurios įvyksta žemyn esančiame sraute (downstream) po catch, nėra gaudomos. Tokias klaidas reikia apdoroti kitu catch žemiau grandinėje arba try-catch aplink surinkėją.

Bendra rekomendacija: vietą, kur dedate klaidų apdorojimą, kuo arčiau klaidos šaltinio, jei tai įmanoma, bet atkreipkite dėmesį, kad catch apdoroja tik kylantį srautą.