https://kotlinlang.org logo
Title
m

Mike Speed

09/24/2021, 1:22 PM
I have a suspend function:
private suspend fun getThing(){...}
How can I set a minimum return time on this? So it will only return if at least 2000ms have passed, for example?
p

Paul Woitaschek

09/24/2021, 1:23 PM
using a delay
m

Mike Speed

09/24/2021, 1:24 PM
literally just
delay(2000)
?
p

Paul Woitaschek

09/24/2021, 1:26 PM
Rather this?
suspend fun getThing() {
  val start = System.currentTimeMillis()

  doStuff()

  val elapsed = System.currentTimeMillis() - start
  delay(2000 - elapsed)
}
m

Mike Speed

09/24/2021, 1:26 PM
That’ll do it! Thanks a lot 🙂
Unless there’s a way to do it in fewer lines? I’m all ears 😄
c

Chris Miller

09/24/2021, 1:29 PM
Maybe something like
delay(2000 - measureTimeMillis { doStuff() })
:nice: 1
🙌 1
p

Paul Woitaschek

09/24/2021, 1:29 PM
suspend fun getThing() : Int {
  return iWillReturnEarliestInTwoSeconds {
    doStuff()
  }
}

suspend inline fun <T> iWillReturnEarliestInTwoSeconds(action: () -> T): T {
  val start = System.currentTimeMillis()

  val result = action()

  val elapsed = System.currentTimeMillis() - start
  delay(2000 - elapsed)

  return result
}
m

Mike Speed

09/24/2021, 1:32 PM
very nice @Chris Miller. I think this
measureTimeMillis{}
is basically doing what you have written here @Paul Woitaschek?
c

Chris Miller

09/24/2021, 1:36 PM
Yes - have a look at the source code for it
👍 1
m

Mike Speed

09/24/2021, 1:36 PM
thanks both
p

Paul Woitaschek

09/24/2021, 1:39 PM
That measure thing doesn't have a return value. Usually getThing indicates that there is a thing to get
m

Mike Speed

09/24/2021, 1:40 PM
yeah true but in my case getThing just updates a LiveData, it’s not returning a value 🙂
j

Joffrey

09/24/2021, 2:03 PM
You have measureTimedValue for getting the elapsed time + the return value (if you need it some other time)
p

Paul Woitaschek

09/24/2021, 2:15 PM
Here we go 😛
suspend inline fun <T> iWillReturnEarliestInTwoSeconds(action: () -> T): T {
  val (result, elapsed) = measureTimedValue(action)
  delay(Duration.seconds(2) - elapsed)
  return result
}
👍 1
I can make it even more cryptic 🙈
suspend inline fun <T> iWillReturnEarliestInTwoSeconds(action: () -> T): T = measureTimedValue(action)
  .also {
    delay(Duration.seconds(2) - it.duration)
  }.value
e

ephemient

09/24/2021, 5:15 PM
just launch a delay, due to how structured concurrency works you won't return until all children are done
private suspend fun getThing() {
    launch { delay(2000) }
    // do other stuff
2
u

uli

09/24/2021, 5:38 PM
Not exactly. You need a scope
private suspend fun getThing() = coroutineScooe {
    launch { delay(2000) }
    // do other stuff
}
👍 1
p

Paul Woitaschek

09/24/2021, 6:17 PM
That is technically correct but probably I wouldn't write it as most of the devs wouldn't understand it
u

uli

09/24/2021, 6:33 PM
They better learn it 😉
Seriously scope is fundamental in coroutines. And waiting for it's children is a key feature of scopes. That's all this method is for.
2
But if you don't like it, feel free to just join launch's job. Might be a bit more expressive i agree
private suspend fun getThing() {
    val delayJob = launch { delay(2000) }
    // do other stuff
    delayJob.join()
🙌 2