xii
06/21/2022, 6:59 PMawaitAll()
with different variables of different types for it to not be casted as Any?Joffrey
06/21/2022, 7:04 PMxii
06/21/2022, 7:08 PMval call1 = call1Request.await()
ephemient
06/21/2022, 7:17 PMsuspend fun <A, B> Pair<Deferred<A>, Deferred<B>>.awaitAll(): Pair<A, B> = Pair(first.await(), second.await())
suspend fun <A, B, C> Triple<Deferred<A>, Deferred<B>, Deferred<C>>.awaitAll(): Triple<A, B, C> = Triple(first.await(), second.await(), third.await())
xii
06/21/2022, 7:19 PMephemient
06/21/2022, 7:22 PMJoffrey
06/21/2022, 7:29 PMawaitAll
on a list of deferred fails on the earliest failure, regardless of order in the list. Using multiple await forces you to wait for all preceding tasks to finish before failing on the await that failsxii
06/21/2022, 7:31 PMephemient
06/21/2022, 7:45 PMsuspend fun <A, B, C> Triple<Deferred<A>, Deferred<B>, Deferred<C>>.awaitAll(): Triple<A, B, C> = try {
Triple(first.await(), second.await(), third.await())
} catch (e: Throwable) {
first.cancel()
second.cancel()
third.cancel()
throw e
}
suspend fun <A, B, C> Triple<Deferred<A>, Deferred<B>, Deferred<C>>.awaitAll(): Triple<A, B, C> = listOf(first, second, third).awaitAll().let { (first, second, third) -> Triple(first as A, second as B, third as C) }
Joffrey
06/21/2022, 7:54 PMcancel
approach solves the problem because the time that you spend waiting before the failure is the problem, not the time afterephemient
06/21/2022, 7:55 PMinvokeOnCompletion
to preserve itgildor
06/22/2022, 3:51 AMUsing multiple await forces you to wait for all preceding tasks to finish before failing on the await that failsNo, if you use own scope. This why I prefer (and use) this version:
suspend fun <A, B, C> awaitTriple(
a: suspend () -> A,
b: suspend () -> B,
c: suspend () -> C,
): Triple<A, B, C> {
return coroutineScope {
val aDeferred = async { a() }
val bDeferred = async { b() }
val cDeferred = async { c() }
Triple(
aDeferred.await(),
bDeferred.await(),
cDeferred.await()
)
}
}