coroutine
이 exception
을 받게 되면, coroutine
스스로
parent를 취소하고, children에게 전파한다.
SupervisorJob
은 child에서 expception 발생해도 cancel
되지 않는다.
fun main() : Unit = runBlocking {
val scope = CoroutineScope(SupervisorJob())
scope.launch {
delay(1000)
throw Error("some Error")
}
scope.launch {
delay(2000)
println("Will be printed")
}
delay(3000)
}
output
Exception : some error
Will be printed
SupervisorJob()
의 경우에는 children이 여러개일 때,
children에서 exception이 발생해도 서로 영향을 주지 않는다는 이점이 있다.
coroutine builders 를 supervisorScope
로 래핑하는 방법이다.
fun main() : Unit = runBlocking {
supervisorScope {
launch {
delay(1000)
throw Error("some Error")
}
launch {
delay(2000)
println("Will be printed")
}
}
delay(1000)
println("Done")
}
suspending function 으로 래핑할 수 있다.
suspend fun notify(actions: List<UserAction>) =
supervisorScope {
actions.forEach{ action ->
launch {
notifyAnalytics(action)
}
}
}
supervisorScope
는 withContext(supervisorJob())
을 대체할 수 없다. withContext
가 supervisorJob
을 부모로 할 뿐, context의 coroutine
은 종료될 것이다.
class MyException : Throwable()
suspend fun main() = supervisorScope {
val str1 = async<String> {
delay(1000)
throw MyException()
}
val str2 = async {
delay(2000)
"Text2"
}
try{
println(str1.await())
} catch (e : MyException) {
println(e)
}
println(str2.await())
}
output
MyException
Text2
만약 exception이 CancellationException
의 하위타입이라면, 부모로 예외를 전파하지 않는다. 오직 해당 coroutine
만 cancellation된다.
CancellationException
은 open class
이기 때문에, 확장가능하다.
object MyNonPropagatingException : CancellationException()
suspend fun main() : Unit = coroutineScope {
launch {
launch {
delay(2000)
println("Wibb not be printed")
}
throw MyNonPropagatingException
}
launch {
delay(2000)
print("Will be printed")
}
}
output
Will be printed
SupervisorJob 과 exceptionHandler 를 추가한 coroutine을 생성.
exception이 발생해도 context에 있는 handler에 의해 error case 별 처리 가능하다.
fun main() : Unit = runBlocking {
val handler =
CoroutineExceptionHandler{ ctx, exception ->
println("Caught $exception")
}
val scope = CoroutineScope(SupervisorJob() + handler)
scope.launch {
delay(1000)
throw Error("some error")
}
scope.launch {
delay(2000)
println("Will be printed")
}
delay(3000)
}
output
Caught java.lang.Error: some error
Will be printed