https://kotlinlang.org logo
Title
k

Kamila

03/31/2022, 6:53 AM
Hi guys! I am trying to learn coroutines, coming from Java background and CompletableFutures: Does this snippet make sense?
private suspend fun fetchExternalData(futures: List<CompletableFuture<Reply>>): List<Reply> = coroutineScope {
        futures.map {
            async {
                it.join()
            }
        }.awaitAll()
    }
I have a list of CompletableFuture, which I would run async and do action when all of them complete. Is this the right place where I call
join
(or
get()
) to get reply? The idea is to get a bunch of request, send them in parallel (fork) and wait for all of them (join), then combine the result
j

Joffrey

03/31/2022, 6:59 AM
You're almost there. The snippet makes sense but you shouldn't use a blocking
join()
in coroutines. A better option is to use the
CompletableFuture.await()
function provided by
kotlinx-coroutines-jdk8
Actually I think you could even use
asDeferred()
directly instead of
async { it.await() }
e

ephemient

03/31/2022, 7:02 AM
you don't need `coroutineScope`+`async` if you use https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-jdk8/kotlinx.coroutines.future/as-deferred.html
private suspend fun fetch(futures: List<CompletableFuture<Reply>>): List<Reply> =
    futures.map { it.asDeferred() }.awaitAll()
the basic idea is sound, but
asDeferred()
also ties cancellation back to the original
Future
it's an important part of structured concurrency that Java's Futures don't really provide support for
j

Joffrey

03/31/2022, 7:09 AM
Just to clarify, both
CompletableFuture.await
and
asDeferred
forward cancellation to the underlying future. Using
join
doesn't.
☝️ 1
e

ephemient

03/31/2022, 7:13 AM
and the easiest thing to write in Java also misses cancellation, whereas kotlinx.coroutines basically enforces structure on its own coroutines and makes it relatively easy in integrations where possible
j

Joffrey

03/31/2022, 7:15 AM
Actually now I'm intrigued because in the docs it's mentioned that
asDeferred().await()
does not forward cancellation. So I guess
Deferred.await()
is cancellable but doesn't cancel the underlying
Deferred
? Weird..
k

Kamila

03/31/2022, 8:59 AM
Thanks guys! ❤️