当我在另一个函数中等待时,如何在 Kotlin 协程中捕获异常?

How can I catch an exception in Kotlin coroutine when I am awaiting it in another function?

抱歉标题模糊,想不出更好的东西。

所以我阅读了 this 文章并想做同样的事情。问题是我不能做 try { promise... } catch (e) { } 导致错误被吞没。我可以在等待它的地方捕捉到错误,但我不希望那样。

我的代码如下所示:

typealias Promise<T> = Deferred<T>

fun <T, R> Promise<T>.then(handler: (T) -> R): Promise<R> = GlobalScope.async(Dispatchers.Main) {
    // using try/catch here works but I don't want it here.
    val result = this@then.await()
    handler.invoke(result)
}

object PromiseUtil {
    fun <T> promisify(block: suspend CoroutineScope.() -> T): Promise<T> = GlobalScope.async { block.invoke(this) }
}

// somewhere in my UI testing it.
try {
    PromiseUtil.promisify { throw Exception("some exp") }
        .then { Log.d("SOME_TAG", "Unreachable code.") }
} catch (e: Exception) {
    Log.d("ERROR_TAG", "It should catch the error here but it doesn't.")
}

我也读过 and ,但我想以某种方式捕获 UI 代码中的错误,并且不想使用 runBlocking { ... }.

谢谢。

异常从未被捕获,因为它从未被 async 调用传播。当调用 await() 时会发生这种情况。

参见 coroutine exception handling

您的代码应该是:

// somewhere in my UI testing it.
try {
    PromiseUtil.promisify { throw Exception("some exp") }
        .then { Log.d("SOME_TAG", "Unreachable code.") }.await() // <--- added await() call
} catch (e: Exception) {
    Log.d("ERROR_TAG", "It should catch the error here but it doesn't.")
}

但这不会编译,因为 await() 是一个挂起函数。因此,它应该更像是:

// somewhere in my UI testing it.
GlobalScope.launch(CoroutineExceptionHandler { coroutineContext, throwable ->
            Log.d("ERROR_TAG", "It will catch error here")
            throwable.printStackTrace()
        }) {
   PromiseUtil.promisify { throw Exception("some exp") }
        .then { Log.d("SOME_TAG", "Unreachable code.") }.await()
}