Scala Futures

A Brief Primer

What Are Futures?

A data structure for managing the results of a concurrent operation.

Futures in Scala

  • Futures are builtin to Scala, in scala.concurrent

  • Since 2.10, Scala Futures have been based on Akka's implementation

  • We're going to talk briefly about how to manage them

  • The Akka docs on Scala Futures are a great guide, too
    • This presentation is based on them...

Execution Contexts

  • Futures need an "Execution Context" to execute on 
  • For now, let's assume we are using the default provided by Scala...
import scala.concurrent._

Creating a Future

import scala.concurrent.Future

val future = Future {
  "Hello" + "World"

future foreach println

These operations are asynchronous ... the println only runs when the Future completes

Creating a Precompleted Future

// Already "done" successfully Future
val future = Future.successful("Yay!")

// Already "failed" Future
val otherFuture = Future.failed[String](
  new IllegalArgumentException("Bang!")


val promise = Promise[String]()

val theFuture = promise.future


Promises are "for later" and can provide a completed Future

Futures as a Monad

  • Futures are Monadic, and can be handled in a stream of operations
  • map, flatMap, and withFilter mean we can do everything we need in a for comprehension, too

map on Futures

val f1 = Future {
  "Hello" + "World"

val f2 = f1 map { x =>

f2 foreach println

map does not mutate the Future, but provides a new one... and doesn't block!

Nesting Futures

val f1 = Future {
  "Hello" + "World"

val f2 = Future.successful(3)

val f3 = f1 map { x =>
  f2 map { y =>
    x.length * y

f3 foreach println

Double mapping gives us a Future[Future[Int]]...

Not good.

Nesting Futures

val f1 = Future {
  "Hello" + "World"

val f2 = Future.successful(3)

val f3 = f1 flatMap { x =>
  f2 map { y =>
    x.length * y

f3 foreach println

Using flatMap will flatten us out...

But it's probably better to use for comprehensions here.

"Conditional Propagation"

val future1 = Future.successful(4)

val future2 = future1.filter(_ % 2 == 0)
future2 foreach println
val failedFilter = future1.filter(_ % 2 == 1).recover {
  // When filter fails, it will have a 
  // java.util.NoSuchElementException
  case m: NoSuchElementException => 0
failedFilter foreach println

If we only want to continue with a Future under certain conditions,  filter helps us out

for comprehensions with Future

val f = for {
  a <- Future(10 / 2) // 10 / 2 = 5
  b <- Future(a + 1) //  5 + 1 = 6
  c <- Future(a - 1) //  5 - 1 = 4
  if c > 3 // Future.filter
} yield b * c //  6 * 4 = 24
// Note that the execution of futures a, b, and c
// are not done in parallel.
f foreach println

Because for comprehensions use map, flatMap, and filter, execution is sequential here.

Composing Futures

  • Scala provides a number of tools for composing Future
  • We're going to use Akka Actors here for a few examples
  • All you really need to know is this: ask returns a Future!

Combining lots of Futures

// oddActor returns odd numbers sequentially from 1 as a List[Future[Int]]
val listOfFutures = List.fill(100)(
  akka.pattern.ask(oddActor, GetNext).mapTo[Int]
// now we have a Future[List[Int]]
val futureList = Future.sequence(listOfFutures)
// Find the sum of the odd numbers
val oddSum =

oddSum foreach println

sequence transforms a List[Future[T]] into a Future[List[T]]

Consider traverse instead

val futureList = Future.sequence((1 to 100) { x => 
  Future(x * 2 - 1))

val oddSum =

oddSum foreach println

The only problem here is sequence creates an intermediate List[Future[Int]]

val futureList = Future.traverse((1 to 100).toList) { x => 
  Future(x * 2 - 1)

val oddSum =

oddSum foreach println

traverse will create a Traversable[Future[T]] without an intermediate List step  here

Using fold with Futures

// Create a sequence of Futures
val futures = for (i <- 1 to 1000) yield Future(i * 2)

val futureSum = Future.fold(futures)(0)(_ + _)

futureSum foreach println

fold here works just like foldLeft

reduce as an Alternative

// Create a sequence of Futures
val futures = for (i <- 1 to 1000) yield Future(i * 2)

val futureSum = Future.reduce(futures)(_ + _)

futureSum foreach println

reduce is useful when we don't have a start value, and instead want to "start" with the result of the first Future

callbacks on Future

  • Futures provide a number of callbacks for result management
  • Each takes a PartialFunction[A, _]
  • These are meant for when you want to Side Effect on a result (they return Unit)
  • The three primary ones:
  • onSuccess - when this Future succeeds... Passes any result type
  • onFailure - when this Future fails... Passes Throwable instances
  • onComplete - when this Future completes ... (passes a scala.util.Try)


future onSuccess {
  case "bar"     => println("Got my bar alright!")
  case x: String => println("Got some random string: " + x)

onSuccess only runs when no Exception is thrown...


future onFailure {
  case ise: IllegalStateException if ise.getMessage == "OHNOES" =>
  //OHNOES! We are in deep trouble, do something!

  case e: Exception =>
  //Do something else

onFailure can "catch" any Exception ...

Note that Future does not "throw" outside itself!


future onComplete {
  case Success(result)  => doSomethingOnSuccess(result)

  case Failure(failure) => doSomethingOnFailure(failure)

onComplete always runs when a Future completes, passing a scala.util.Try (instances of Success[T] or Failure[Throwable])

falling back

val future4 = future1 fallbackTo future2 fallbackTo future3

future4 foreach println

fallbackTo combines two Future instances, holding the successful value of the second Future if the first fails


val future3 = future1 zip future2 map { case (a, b) => 
  a + " " + b 

future3 foreach println

We can also zip two Future instances together creating a Tuple of successful results

Handling Exceptions with a value

  • Remember that onFailure and onComplete return Unit and are only useful for Side Effects like logging

  • If you need to handle an Exception returning a default result, use recover and recoverWith


val future = akka.pattern.ask(actor, msg1) recover {
  case e: ArithmeticException => 0

future foreach println

recover lets us return a "default" value in the case of an Exception

recovering with another Future

val future = akka.pattern.ask(actor, msg1) recoverWith {

  case e: ArithmeticException => Future.successful(0)

  case foo: IllegalArgumentException =>
    Future.failed[Int](new IllegalStateException("All br0ken!"))


future foreach println

recoverWith is to flatMap as recover is to map...

Useful when you want to "recover" with another Future


Scala Futures

By Brendan McAdams

Scala Futures

  • 1,531
Loading comments...

More from Brendan McAdams