Reputation: 89
Sorry for the vague title, couldn't come up with something better.
So I read this article and wanted to do the same. problem is that I can't do try { promise... } catch (e) { }
cause the error gets swallowed. I can catch the error where I await it, but I don't want that.
and my code looks like this:
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 = [email protected]()
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 I read this and this one too, but I want to somehow catch errors in the UI code, and don't want to use runBlocking { ... }
.
Thanks.
Upvotes: 1
Views: 2580
Reputation: 9170
The exception is never caught because it's never propagated by the async
call. That happens when await()
is called.
See coroutine exception handling.
Your code should be:
// 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.")
}
But this won't compile as await()
is a suspending function. Therefore, it should be more like:
// 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()
}
Upvotes: 5