Sobes.tech
Middle

Flow-догу каталардын иштетилиши жөнүндө эмне билесиз?

sobes.tech AI

AIден жооп

Flow у Kotlin Coroutines прапануе некалькі спосабаў апрацоўкі памылак:

  1. Аператар catch: Захоплівае выключэнні ў ўзвышаючым патоку і дазваляе выканаць дзеянне (напрыклад, рэгістрацыю, вяртанне рэзервовых дадзеных) або замяніць паток.

    flow {
        emit(1)
        throw RuntimeException("Адбылася памылка")
    }.catch { e: Throwable ->
        // Апрацоўка памылкі
        emit(-1) // Вылучэнне іншага значэння пры памылцы
    }.collect { value ->
        // Апрацоўка значэнняў
    }
    
  2. Блок try-catch: Класічны спосаб апрацоўкі выключэнняў вакол часткі кода, уключаючы збор Flow.

    try {
        flow {
            emit(1)
            throw RuntimeException("Адбылася памылка")
        }.collect { value ->
            // Апрацоўка значэнняў
        }
    } catch (e: Throwable) {
        // Апрацоўка памылкі
    }
    

    Гэты спосаб захоплівае памылкі, якія ўзнікаюць пры зборы Flow, але не памылкі, якія выклікае сам эмитэнт Flow да збору.

  3. Аператар onEach з try-catch: Калі трэба апрацаваць памылкі для кожнага элемента асобна.

    flow {
        emit(1)
        emit(2)
        throw RuntimeException("Памылка пасля 2")
        emit(3)
    }.onEach { value ->
        try {
            // Апрацоўка кожнага элемента
            if (value == 2) throw IllegalArgumentException("Няправільнае значэнне 2")
        } catch (e: Throwable) {
            // Апрацоўка памылкі для канкрэтнага value
            println("Памылка для значэння $value: ${e.message}")
            // Можна перакінуць выключэнне далей, калі трэба спыніць паток
            throw e
        }
    }.catch { e: Throwable ->
        // Апрацоўка памылак, якія не былі злавлены ў onEach, або памылак, якія былі выкінуты пасля onEach
        println("Канчатковая памылка: ${e.message}")
    }.collect { value ->
        println("Збіраная значэнне: $value")
    }
    
  4. Аператар retry / retryWhen: Дазваляюць паўтарыць крыніцу Flow пры ўзнікненні памылкі.

    • retry: проста паўтарае спробу зададзеную колькасць разоў.
    • retryWhen: дазваляе вызначыць умову для паўтору.
    var attempt = 0
    flow {
        println("Паспрабуй ${++attempt}")
        if (attempt < 3) throw RuntimeException("Паўторная спроба")
        emit(10)
    }.retryWhen { cause, attempt ->
        // Логіка для вызначэння, ці трэба паўтарыць
        cause is RuntimeException && attempt < 3
    }.collect { value ->
        println("Поспех: $value")
    }
    
  5. Перадача выключэнняў: Памылкі, якія не былі адкрыта злавлены, будуць перададзены ўверх па ланцугу Flow і могуць быць злавлены ў блоке try-catch вакол збіральніка Flow або аператару catch.

Важна зразумець, што аператар catch захоплівае памылкі ў ўзвышаючым патоку (upstream). Памылкі, якія ўзнікаюць у ніжэйшым патоку (downstream) пасля catch, не захопліваюцца. Для апрацоўкі такіх памылак трэба выкарыстоўваць іншы catch ніжэй па ланцугу або try-catch вакол збіральніка.

Агульная рэкамендацыя: размяшчайце апрацоўку памылак як мага бліжэй да крыніцы памылкі, калі гэта магчыма, але ўлічвайце, што catch апрацоўвае толькі ўзвышаючы паток.