[英]Kotlin Coroutines Flow catch mechanism
在我的示例中,我正在调用.network 操作并发出成功案例,但出现错误,例如 404 应用程序崩溃而没有发出异常。 使用 try catch 投降可以防止崩溃,但我想像成功案例一样将错误传递到 ui 层。
suspend fun execute(
params: Params,
):
Flow<Result<Type>> = withContext(Dispatchers.IO) {
flow {
emit(Result.success(run(params)))
}.catch {
emit(Result.failure(it))
}
}
如果你想使用流,你可以使用流的catch
方法。 正如您所说,您可以使用try-catch
但它会破坏结构化并发,因为它也会捕获取消异常或者它会避免抛出取消异常。 您可以做的一件事是在启动调用suspend
function 的根协程时使用异常处理程序。
val coroutineExceptionHandler = CoroutineExceptionHandler { _, exception ->
// handle it
}
scope.launch(handler) { // root coroutine
execute(params)
somethingThatShouldBeExecutedOnlyIfPreviousCallDoesNotThrow()
}
该解决方案适用于流和非流协程。
在带有runCatching
的解决方案中,您必须手动检查第一次执行的结果以避免第二次运行。 这里有一个有趣的线程。
有一个有用的 function runCatching
可以轻松创建结果,但协程中的问题是您不想吞下 CancellationExceptions。 所以在下面,我在此处的回答中使用runCatchingCancellable
。
这不应该是 Flow,因为它返回单个项目。
如果run
不是阻塞 function(如果您使用带有挂起函数的 Retrofit 则不应该是),您的代码可以简单地是:
suspend fun execute(params: Params): Result<Type> = runCatchingCancellable {
run(params)
}
如果它是一个阻塞 function 你可以使用:
suspend fun execute(params: Params): Result<Type> = runCatchingCancellable {
withContext(Dispatchers.IO) {
run(params)
}
}
如果您要返回一个流程(您不应该返回一个项目,!),那么您不应该将其设为suspend
function,并且您应该在flow
构建器 lambda 中捕获错误:
fun execute(params: Params): Flow<Result<Type>> = flow {
emit(runCatchingCancellable {
run(params)
})
}
// or if run is blocking (it shouldn't be):
fun execute(params: Params): Flow<Result<Type>> = flow {
emit(runCatchingCancellable {
withContext(Dispatchers.IO) { run(params) }
})
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.