Reputation: 113
I had a code that looks like below
fun main() {
viewModelScope.launch {
doA()
//call api with Flow as the return type
}
}
suspend fun doA() {
viewModelScope.async { doB() }.await()
}
suspend fun doB() {
//Do logic here, eventually will call line below
viewModelScope.launch { doC() }
}
suspend fun doC() {
//call api with Flow as the return type
}
What I want to achieve here is to make the doA()
wait till it's done and after that continue to the function below it, which is the call API function. But when I try to run, the doA()
not wait until everything finishes on that side. The debug quite help me and I found that when the doB()
being run and reach the doC()
which in the new scope, the program continues to the next line after the doA()
in main()
.
Is there's something I missing? Why the code doesn't work like what I want? I kind a new in Coroutine to say. And yes, I run the code in the Android environment. Thanks for helping
Upvotes: 2
Views: 3200
Reputation: 101
Me too Beginner. As per my LIMITED UNDERSTANDING, "async" should be used for running "parallel" jobs and wait for "future results"
For getting the jobs done "sequentially", instead "launch" and "join" should be used. Plz check Waiting for a job
Regarding the doA() finishing while doB() is running, its because in doB(), a NEW COROUTINE is launched and it immediately returns, hence the Execution continues with the Next Line in doA(). To make doA() wait, add "join" in doB() while launching the Coroutine
fun main() {
viewModelScope.launch {
doA()
//call api with Flow as the return type
}
}
suspend fun doA() {
//viewModelScope.async { doB() }.await()
// Replace with "launch" and "join"
viewModelScope.launch{ doB() }.join()
}
suspend fun doB() {
//Do logic here, eventually will call line below
//viewModelScope.launch { doC() }
// Add join() to make it wait
viewModelScope.launch { doC() }.join()
}
suspend fun doC() {
//call api with Flow as the return type
}
But if you prefer to keep using "async", then just add "join" in doB()
suspend fun doB() {
//Do logic here, eventually will call line below
//viewModelScope.launch { doC() }
// Add join() to make it wait
viewModelScope.launch { doC() }.join()
}
Upvotes: 5
Reputation: 2732
For doB()
and doC()
you're creating new coroutine to run, so it doesn't run in same coroutine as doA()
. So, technically doA() has completed its execution. To make doA()
wait, you have to run doB() and doC() in same coroutine.
suspend fun doA() {
doB()
}
suspend fun doB() {
//Do logic here, eventually will call line below
doC()
}
suspend fun doC() {
//call api with Flow as the return type
}
Also, do not use async-await
if you're using await
immediately after async
like viewModelScope.async { doB() }.await()
because it is same as launch
.
Upvotes: 1