我一直难以确定协程的错误处理,我已经按照以下步骤缩小了单元测试的范围:
这很好。但是,当我尝试使用相同的协程范围来启动新的协程时,总是会例外地完成,但有相同的例外。
这是测试:
fun `when you throw an exception in a coroutine scope, is the coroutine scope dead?`() {
val parentJob = Job()
val coroutineScope = CoroutineScope(parentJob + Dispatchers.Default)
val deferredResult = coroutineScope.async { throw IllegalStateException() }
runBlocking {
try {
deferredResult.await()
} catch (e: IllegalStateException) {
println("We caught the exception. Good.")
}
try {
coroutineScope.async { println("we can still use the scope") }.await()
} catch (e: IllegalStateException) {
println("Why is this same exception still being thrown?")
}
}
}
这是测试的输出:
We caught the exception. Good.
Why is this same exception still being thrown?
为什么会这样?
我应该如何处理异常?
Either<Result, Exception>
吗? 请注意,我正在使用Kotlin 1.3
答案 0 :(得分:5)
当您在合并范围中启动协程时(使用STATICFILES_DIRS = (
os.path.join(BASE_DIR, 'static'),
)
STATIC_URL = '/static/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media/')
MEDIA_URL = '/media/'
或async
),默认情况下,协程失败会取消该范围,以立即取消所有其他子级。这种设计避免了晃动和丢失异常。
这里的一般建议是:
除非确实需要并发,否则不要使用launch
/ async
。使用挂起函数设计代码时,不需要使用await
和async
。
如果确实需要并发执行,请遵循以下模式:
await
如果您需要处理并发操作的失败,请在coroutineScope {
val d1 = async { doOne() }
val d2 = async { doTwo() }
...
// retrieve and process results
process(d1.await(), d2.await(), .... )
}
周围加上try { ... } catch { ... }
来捕获任何并发执行的操作中的失败。
coroutineScope { ... }
)允许细粒度的异常处理。您可以在文档https://kotlinlang.org/docs/reference/coroutines/exception-handling.html