https://kotlinlang.org logo
Title
j

julioromano

08/05/2021, 11:02 AM
I have a suspend function which calls other 3 suspending functions. How can I have
doSomething
call the 3 suspending functions serially? (i.e. waiting for each one to complete before calling the other?)
suspend fun doSomething() {
    suspendingFun1()
    suspendingFun2()
    suspendingFun3()
  }
🧵
Right now I came up with:
suspend fun doSomethingInSerially() {
    coroutineScope {
      async { suspendingFun1() }.await()
      async { suspendingFun2() }.await()
      async { suspendingFun3() }.await()
    }
  }
But I don’t know if it’s correct. And the IDE suggest me all those
async {}.await()
calls are redundant and to replace them with
withContext(Dispatchers.Default) {}
instead 🤷
r

Richard Gomez

08/05/2021, 11:04 AM
@julioromano: Your first example should work. 🤔
8
suspend fun doSomething() {
    val thing1 = suspendingFun1()
    val thing2 = suspendingFun2(thing1)
    suspendingFun3(thing2)
  }
s

streetsofboston

08/05/2021, 11:40 AM
I agree with @Richard Gomez. Your original example already calls all three of them sequentially. That is the beauty of suspend functions. They are asynchronous, but you can call them like they are regular functions, imperatively/sequentially.
j

julioromano

08/05/2021, 11:50 AM
True, I’ll have to double check what those functions do internally as I had the impression that running them like so yielded parallel network calls. Thanks for your input!
s

streetsofboston

08/05/2021, 12:12 PM
It is easier to visualize that they are called sequentially when using an example where they return a value and take input
suspend fun doSomething(): Int {
    val res1 = suspendingFun1()
    val res2 = suspendingFun2(res1)
    return suspendingFun3(res2)
  }
k

Kareem Waleed

08/05/2021, 12:51 PM
If you need to lunch them sequentially then wait for all three of them to finish you’ve to modify your code as follows
suspend fun doSomethingInSerially() = coroutineScope {
        val job1 = launch { suspendingFun1() }
        val job2 = launch { suspendingFun2() }
        val job3 = launch { suspendingFun3() }
        joinAll(job1, job2, job3)
    }
this would do what you need if you don’t expect a result from your async functions
r

Richard Gomez

08/05/2021, 1:05 PM
@Kareem Waleed Wouldn't the use of
coroutineScope
implicitly wait for all of them to finish?
suspend fun doSomethingInSerially() = coroutineScope {
        launch { suspendingFun1() }
        launch { suspendingFun2() }
        launch { suspendingFun3() }
}
https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/coroutine-scope.html "This function returns as soon as the given block and all its children coroutines are completed"
☝️🏼 1
☝️ 2
:yes: 4
k

Kareem Waleed

08/05/2021, 3:32 PM
@Richard Gomez Yes, actually the use of
join()
in my example is redundant. sorry 😄
👍 2
👍🏼 1
m

myanmarking

08/06/2021, 11:09 AM
the IDE is right. That is sequential:
suspend fun doSomethingInSerially() {
    coroutineScope {
      async { suspendingFun1() }.await()
      async { suspendingFun2() }.await()
      async { suspendingFun3() }.await()
    }
  }