simon.vergauwen
01/21/2019, 1:12 PMDeferred<A>? I was expecting to be able to define a handleErrorWith operator that wraps an existing Deferred to recover from errors but the program results in the original error.Allan Wang
01/21/2019, 2:25 PMlouiscad
01/21/2019, 3:03 PMcoroutineScope { ... }, and catch exceptions outside of it for this to work properly. That is structured concurrency.
Also, most of the time, you won't need Deferred nor async and await because suspend fun, withContext and launch satisfy most use cases.simon.vergauwen
01/21/2019, 3:11 PMDeferred with coroutineScope can prevent this?simon.vergauwen
01/21/2019, 3:11 PMDeferred specific implementationAllan Wang
01/21/2019, 3:14 PMhandleErrorWith create the deferred executions? Otherwise I’m not sure there’s anything you can do to stop parent cancellation unless the deferred creator implements itsimon.vergauwen
01/21/2019, 3:15 PMDeferred there is no way to know what code is underneath.louiscad
01/21/2019, 3:19 PMasync calls more specifically.louiscad
01/21/2019, 3:19 PMsimon.vergauwen
01/21/2019, 3:19 PMDeferred I am wrapping.simon.vergauwen
01/21/2019, 3:20 PMfun <A> CoroutineScope.handleErrorWith(fa: Deferred<A>, f: (Throwable) -> Deferred<A>): Deferred<A> =
async(start = CoroutineStart.LAZY) {
try {
coroutineScope {
fa.await()
}
} catch (e: Throwable) {
f(e).await()
}
}Allan Wang
01/21/2019, 3:23 PMSupervisorJob to your caller context (which you can’t control)Allan Wang
01/21/2019, 3:23 PMAllan Wang
01/21/2019, 3:25 PMimport kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.CoroutineStart
import kotlinx.coroutines.Deferred
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.async
import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.plus
import kotlinx.coroutines.runBlocking
import kotlin.test.Test
class Test {
fun <A> CoroutineScope.handleErrorWith(fa: Deferred<A>, f: (Throwable) -> Deferred<A>): Deferred<A> =
async(start = CoroutineStart.LAZY) {
try {
fa.await()
} catch (e: Throwable) {
f(e).await()
}
}
@Test
fun t() = runBlocking {
val result =
with(CoroutineScope(Dispatchers.Default) + SupervisorJob()) {
handleErrorWith(async(start = CoroutineStart.LAZY) {
throw RuntimeException("Boom!")
}) {
async { it.message }
}
}
val r = result.await() //threw RuntimeException("Boom!") but expected String of value "Boom!"
println(r)
}
}simon.vergauwen
01/21/2019, 3:42 PM