As you mentioned blocking is bad and you only should use it in testing.

Here is a nice Blog that describes the possibilities: testing-future-objects-scalatest

In real life you should use for example this:

  futureResult.foreach { x: String =>
    // do some side effect

All you have to make sure is that the process that calls this Future is not stopped (that is for example in a test the case)

Another solution is to use the Async - Await construct that has alos an implementation in Scala: scala-async


The best practice is to do a Await "at the end of the world". This means that you should combine all your futures in a single future and then Await only once.

val f1 = (ping1 ? AskingTest).mapTo[String]
val f2 = (ping2 ? AskingTest).mapTo[String]

val combinedFuture: Future[(String, String)] = for {
  str1 <- f1
  str2 <- f2
} yield (str1, str2)

// final await at the end of program
val (str1, str2) = Await.result(combinedFuture, Duration.Inf)

When I started to write code with Futures, I used to write Await at every line. which is wrong because it defeats the purpose of using Futures.

So your goal is to combine as many futures as possible using for and then Await only once.

The other solutions you have listed above are also OK except No 4 because it can lead to your program crashing if the future is not complete yet.

Related Query

More Query from same tag