Android 공부/Coroutine

[XX캠퍼스] 14.Kotlin Coroutines & Flow ( 예외처리하기 )

Machine_웅 2022. 7. 27. 14:18
728x90
반응형

https://dalinaum.github.io/coroutines-example/14

 

플로우 예외처리하기

플로우 예외처리하기 예제 71: 수집기 측에서 예외처리하기 예외는 collect을 하는 수집기 측에서도 try-catch 식을 이용해 할 수 있습니다. import kotlinx.coroutines.* import kotlinx.coroutines.flow.* fun simple(): Fl

dalinaum.github.io

 

try-catch 식을 이용

catch() 연산자를 이용해 업스트림에서만 예외처리 

 

수집기 측에서 예외처리하기

예외는 collect을 하는 수집기 측에서도

try-catch 식을 이용해 할 수 있습니다.

 

import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*

fun simple(): Flow<Int> = flow {
    for (i in 1..3) {
        println("Emitting $i")
        emit(i) // emit next value
    }
}

fun main() = runBlocking<Unit> {
    try {
        simple().collect { value ->         
            println(value)
            check(value <= 1) { "Collected $value" }
        }
    } catch (e: Throwable) {
        println("Caught $e")
    } 
}

check(value <= 1) { "Collected $value" }  // 여기서 예외가 발생 

 

 

 

 

모든 예외는 처리가능

어느 곳에서 발생한 예외라도 처리가 가능합니다.

import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*

fun simple(): Flow<String> = 
    flow {
        for (i in 1..3) {
            println("Emitting $i")
            emit(i) // emit next value
        }
    }
    .map { value ->
        check(value <= 1) { "Crashed on $value" }                 
        "string $value"
    }

fun main() = runBlocking<Unit> {
    try {
        simple().collect { value -> println(value) }
    } catch (e: Throwable) {
        println("Caught $e")
    } 
}

 .map { value ->
        check(value <= 1) { "Crashed on $value" }                 
        "string $value"
    }

 

flow 코드 내에서 예외가 나도 잡을수 있다. 

 

 

 

예외 투명성 (권장 )

빌더 코드 블록 내에서 예외를 처리하는 것은 예외 투명성을 어기는 것입니다.

( 플로우 내부에서 예외 처리시, 밖에서는 예외가 발생했는지 알수 없다. )

 

플로우에서는 catch 연산자를 이용하는 것을 권합니다.

catch 블록에서 예외를 새로운 데이터로 만들어 emit을 하거나,

다시 예외를 던지거나, 로그를 남길 수 있습니다.

 

import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*

fun simple(): Flow<String> = 
    flow {
        for (i in 1..3) {
            println("Emitting $i")
            emit(i) // emit next value
        }
    }
    .map { value ->
        check(value <= 1) { "Crashed on $value" }                 
        "string $value"
    }

fun main() = runBlocking<Unit> {
    simple()
        .catch { e -> emit("Caught $e") } // emit on exception
        .collect { value -> println(value) }
}

실행결과 
Emitting 1
string 1
Emitting 2
Caught java.lang.IllegalStateException: Crashed on 2

 .catch { e -> emit("Caught $e") } // emit on exception

 

 

catch 투명성

catch 연산자는 업스트림(catch 연산자를 쓰기 전의 코드)에만 영향을 미치고

다운스트림에는 영향을 미치지 않습니다. 이를 catch 투명성이라 합니다.

 

import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*

fun simple(): Flow<Int> = flow {
    for (i in 1..3) {
        println("Emitting $i")
        emit(i)
    }
}

fun main() = runBlocking<Unit> {
    simple()
        .catch { e -> println("Caught $e") } // does not catch downstream exceptions
        .collect { value ->
            check(value <= 1) { "Collected $value" }                 
            println(value) 
        }
}

실행결과 
Emitting 1
1
Emitting 2
Exception in thread "main" java.lang.IllegalStateException: Collected 2
 at FileKt$main$1$2.emit (File.kt:15) 
 at FileKt$main$1$2.emit (File.kt:14) 
 at kotlinx.coroutines.flow.FlowKt__ErrorsKt$catchImpl$2.emit (Errors.kt:158)

        .catch { e -> println("Caught $e") }  // simple() 에서 발생하는 예외만 다룰수 있음. 
        .collect { value ->   // 여기는 다운 스트림이기때문에 예외를 처리할 수 없다. 
            check(value <= 1) { "Collected $value" }                 
            println(value) 
        }

 

 

 

 

728x90
반응형