https://kotlinlang.org logo
#coroutines
Title
# coroutines
t

torres

07/26/2020, 8:35 AM
is there any difference in terms of efficiency between doing this
urls.map {
GlobalScope.async { fetchLink(it) }
}.awaitAll().flatMap { it }
versus doing this?
urls.map {
GlobalScope.async { fetchLink(it) }
}.flatMap { it.await() }
o

octylFractal

07/26/2020, 8:36 AM
assuming
urls
is a List, yes --
.awaitAll()
will build an extra list
as a point of coroutines, there's no difference, but I will say you shouldn't be using
GlobalScope
here most likely
t

torres

07/26/2020, 8:37 AM
huh? what should I be using instead?
i want to fetchLinks in parallel? @octylFractal
o

octylFractal

07/26/2020, 8:38 AM
if you're already in a
suspend
context:
Copy code
coroutineScope {
  urls.map { async { fetchLink(it) }.flatMap { it.await() }
}
if you're not, replace
coroutineScope
with
runBlocking(Dispatchers.Default)
t

torres

07/26/2020, 8:38 AM
yes
urls
is a List
okay thanks. I am not in the suspend context. i dont understand why not use GlobalScope here?
o

octylFractal

07/26/2020, 8:39 AM
doing it this way ensures that if one of the
async
calls fails, it will cancel all of the other
async
calls properly, and ensure that exceptions are propagated properly
t

torres

07/26/2020, 8:41 AM
interesting, is there a docs about this @octylFractal as I would love to read more? so basically i will use runblocking and the flatmap version is what your suggesting?
o

octylFractal

07/26/2020, 8:42 AM
https://medium.com/@elizarov/the-reason-to-avoid-globalscope-835337445abc is probably one of the better articles about explicitly why not to use GlobalScope
a

araqnid

07/27/2020, 4:15 PM
awaitAll
will fail as soon as one of the
fetchLink
calls fails, as opposed to only as soon as the
fetchLink
calls before it in the list have completed/failed i.e. if the calls are taking a long time, it can make a difference to use
awaitAll
, as that would propagate a failure sooner (and cancel the siblings)
t

torres

07/28/2020, 8:31 AM
thanks @araqnid but thats that opposite of what @octylFractal said?
“*Octavia Togami*  [9:39 AM] doing it this way ensures that if one of the 
async
 calls fails, it will cancel all of the other 
async
 calls properly, and ensure that exceptions are propagated properly”
a

araqnid

07/28/2020, 8:32 AM
That will happen whether you call await() on each or awaitAll() on the list, and using a coroutineScope{} to isolate the cancellation to just these fetches is still advisable
o

octylFractal

07/28/2020, 8:33 AM
hmm, yes, I was not aware that
awaitAll()
had differing behavior
g

gildor

07/28/2020, 12:48 PM
If you use proper coroutineScope, or any other wrapping scope, there is no difference in behavior of await() and awaitAll(), because parent Job also will be cancelled on first fail As was said before, you shouldn't really use GlobalScope in such case
t

torres

07/28/2020, 1:35 PM
thanks all
l

Lukas Lechner

07/29/2020, 1:48 PM
@gildor You are right! I tested it out. But why is the official documentation saying the exact opposite? https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/await-all.html
g

gildor

07/29/2020, 1:49 PM
I believe it's just a bit obsolete doc
Yes, awaitAll() is not exactly the same, it was important before introduction of structured concurrency
But after introduction of structured concurrency and when default Job cancellation startegy was changed (before it worked as SupervisorJob), it has the same behaviour
So now this doc should be changed and should say that it's not the same with SupervisorJob or without using parent scope
👍 2
4 Views