Scala Futures
Examples
Creating a Future
import scala.concurrent.Future
import scala.concurrent.ExecutionContext.Implicits.global
object FutureDivider {
def divide(a: Int, b: Int): Future[Int] = Future {
// Note that this is integer division.
a / b
}
}
Quite simply, the divide method creates a Future that will resolve with the quotient of a over b.
Consuming a Successful Future
The easiest way to consume a successful Future-- or rather, get the value inside the Future-- is to use the map method. Suppose some code calls the divide method of the FutureDivider object from the "Creating a Future" example. What would the code need to look like to get the quotient of a over b?
object Calculator {
def calculateAndReport(a: Int, b: Int) = {
val eventualQuotient = FutureDivider divide(a, b)
eventualQuotient map {
quotient => println(quotient)
}
}
}
Consuming a Failed Future
Sometimes the computation in a Future can create an exception, which will cause the Future to fail. In the "Creating a Future" example, what if the calling code passed 55 and 0 to the divide method? It'd throw an ArithmeticException after trying to divide by zero, of course. How would that be handled in consuming code? There are actually a handful of ways to deal with failures.
Handle the exception with recover and pattern matching.
object Calculator {
def calculateAndReport(a: Int, b: Int) = {
val eventualQuotient = FutureDivider divide(a, b)
eventualQuotient recover {
case ex: ArithmeticException => println(s"It failed with: ${ex.getMessage}")
}
}
}
Handle the exception with the failed projection, where the exception becomes the value of the Future:
object Calculator {
def calculateAndReport(a: Int, b: Int) = {
val eventualQuotient = FutureDivider divide(a, b)
// Note the use of the dot operator to get the failed projection and map it.
eventualQuotient.failed.map {
ex => println(s"It failed with: ${ex.getMessage}")
}
}
}