```coroutineScope { launch { foo() } bar()...
# coroutines
u
Copy code
coroutineScope {
    launch { foo() }
    bar()
}
Copy code
coroutineScope {
    launch { foo() }
    launch { bar() }
}
are these equivalent?
nope 2
b
Yes in terms of execution order
j
You definitely can observe different execution orders between those
b
Really? On what scenarios?
j
well I think the only time you wouldn't see a difference is if you were in an Unconfined dispatcher
j
call it in runBlocking and you'll get different execution order
j
if your mental model of
launch
is "post this to a queue" then if you don't post
bar
but instead execute it synchronously after posting
foo
it will run first
u
but if I don't care about the order of getting started, and I only care that
coroutineScope
will await them both, then it doesn't matter/first has less overhead?
b
Ah, gotcha. It's like js event loop shit all over again! Apologies for spreading misinformation!
k
A coroutinescope will always wait for all of its children to finish before it can itself finish
j
if the first line in`bar()` was
yield()
then they might appear to be in the same order
e
after
launch { foo() }
, it is not specified how much of
foo
has run before the next statement in the caller
j
that still depends on scheduling and dispatcher support of
yield
, but yes they might be the same sometimes
really you can't saying anything without knowing the dispatcher in use (with respect to order)
e
with
launch(start = CoroutineStart.UNDISPATCHED) { foo() }
you can say that up to the first suspension point in
foo()
has executed, I believe
and with
launch(start = CoroutineStart.LAZY) { foo() }
you should be able to say that none of it has executed
but otherwise… unspecified
u
so given
io
dispatcher, then what is more idiomatic, if you only care that they're executed in parallel a nd coroutineScope awaits both of them
j
sure, but now you're changing the code. if the caller is using the Unconfined dispatcher
foo
will always run before
bar
j
I don't think one is more idiomatic than the other
e
I'd write whichever is clearer for the purpose
u
well that's my question, what does look more clearer 😄 basically I want to sync two apis at once
Copy code
coroutineScope {
	launch { syncInvoices() }
	launch { syncMessages() }
}
probably the dual launch makes it more apparent that they're both going in parallel?
c
If the main thing you’re trying to express is 2 jobs running in parallel, I would make sure that’s explicit in the code. So yes, like the snippet above, I’d use 2
launch
blocks
e
if both launches are equally "async", then yes I'd write them both as
launch
u
thanks!
and technically this
Copy code
coroutineScope {
	launch { syncInvoices() }
	syncMessages()
}
says "syncMessages after enqueueing syncInvoices coroutine" ?
e
that's one way to look at it
g
It is, but if one has to add one more "sync", they may be confused how to do this. So 2 launch blocks are easier to read and shows intent better