-1

I need the result variable below to contain Future[(String,String,String)] with the result of futures f1, f2 and f3, but instead I'm getting Future[((String, String), String)]. I need the three futures to run in parallel. How to make this work?

  def futureA = Future { "A" }
  def futureB = Future { "B" }
  def futureC = Future { "C" }

  def futureFunc = {

       val cond1 = 1
       val cond2 = 0

       val f1 = if (cond1 > 0) 
             futureA
       else 
             Future {""} 

       val f2 = if (cond2 > 0) 
             futureB
       else 
             Future {""} 

       val f3 = futureC

       val fx = f1.zip(f2)

       val result = fx.zip(f3)

  }
ps0604
  • 1,227
  • 23
  • 133
  • 330
  • Please, try to understand the answers to the questions you already asked (possibly by asking for more details), instead of asking multiple variants of the same basic question. – Cyrille Corpet May 05 '17 at 12:48

2 Answers2

2

If you create your futures beforehand, you can combine them in a for comprehension and they will run in parallel:

for {
  a <- f1
  b <- f2
  c <- f3
} yield (a, b, c)

res0: scala.concurrent.Future[(String, String, String)]
Sascha Kolberg
  • 7,092
  • 1
  • 31
  • 37
0

I tried to create more solutions and here is result:

  def futureFunc = {

    val cond1 = 1
    val cond2 = 0

    val f1 = if (cond1 > 0)
      futureA
    else
      Future {""}

    val f2 = if (cond2 > 0)
      futureB
    else
      Future {""}

    val f3 = futureC
//#1
    Future.sequence(List(f1, f2, f3)).map {
      case List(a, b, c) => (a, b, c)
    }
//#2
    for{
      f11 <- f1
      f22 <- f2
      f33 <- f3
    } yield (f11, f22, f33)
//#3
    f1.zip(f2).zip(f3).map{
      case ((f11,f22),f33) => (f11,f22,f33)
    }

  }

First one uses Future sequence, for creating Future[List[]] and then mapping this list for tuple (because of type safety we don't have method for tupling list).

Second is usage of for comprehension as described by Sascha, as you may know it is syntactic sugar for maps and flatmaps which is preferred to work with futures.

Last one is using zips, as you wanted, but you still need to map last future to obtain tuple which you want.

All operations are non blocking, but for all operations you need to know exactly futures which you will be using. You can use additional libraries for tupling lists, and then use first solution for not well known amount for futures. For readability i think for comprehension is best.

Kamil Banaszczyk
  • 1,133
  • 1
  • 6
  • 23
  • for comprehension runs the futures in parallel or sequentially? – ps0604 May 05 '17 at 13:01
  • for comprehensions is syntactic sugar for maps, as you can see higher, Futures starts running as soon as you create them. In your code you can assume that futures are completed while declared, because you tried to run only creating String in new thread (i assume that you know that most of your futureFunc will work sequentially). So for comprehension will map all promised values into tuple, and when all futures (which runs in parallel from the time when you created them) will be completed you then can obtain (str,str,str) values from your Future. Is that clear for you? – Kamil Banaszczyk May 05 '17 at 13:04