繁体   English   中英

Kotlin Coroutines Flow catch 机制

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM