mavrav
mavrav

Reputation: 580

How to wait for result of Scala Futures in for comprehension

I am having a issue with the below piece of code. I want 'combine' method to get triggered after all groundCoffee,heaterWater,frothedMilk method completes. They would be triggered concurrently.All the 4 methods grind,heatWater,frothMilk,brew are concurrently executed using a future.

def prepareCappuccino(): Future[Cappuccino] = {
  val groundCoffee = grind("arabica beans")
  val heatedWater = heatWater(Water(20))
  val frothedMilk = frothMilk("milk")
  for {
    ground <- groundCoffee
    water <- heatedWater
    foam <- frothedMilk
    espresso <- brew(ground, water)
  } yield combine(espresso, foam)
}

When I execute the above method the output I am getting is below

start grinding...
heating the water now
milk frothing system engaged!

And the program exits after this. I got this example from a site while I was trying to learn futures. How can the program be made to wait so that combine method get triggered after all the futures return?

Upvotes: 0

Views: 2654

Answers (2)

sksamuel
sksamuel

Reputation: 16397

The solution already posted to Await for a future is a solution when you want to deliberately block execution on that thread. Two common reasons to do this are for testing, when you want to wait for the outcome before making an assertion, and when otherwise all threads would exit (as is the case when doing toy examples).

However in a proper long lived application Await is generally to be avoided.

Your question already contains one of the correct ways to do future composition - using a for comprehension. Bear in mind here, that for-comprehensions are converted to flatMaps, maps and withFilter operations, so any futures you invoke in the for-comprehension will only be created after the others complete, ie serially.

If you want a bunch of futures to operate in concurrently, then you would create them before entering the for-comprehension as you have done.

Upvotes: 1

codejitsu
codejitsu

Reputation: 3182

You can use the Await here:

val f = Future.sequence(futures.toList)
Await.ready(f, Duration.Inf)

I assume, you have all the futures packed in a list. The Await.ready makes all the waiting work.

Upvotes: 0

Related Questions