Scala’s Futures bring a functional approach to asynchronous programming and let you escape callback hell!

On a high level, using Futures is just a different style from using callbacks. For example, in Javascript the general way to handle asynchronous calls is something along the lines of

doSomethingAsync(function(result, err){
    if(err) {...} //handle error
    else {...} //handle result
})

With futures’ style, the same operation would look like

doSomethingAsync
    .onSuccess(function(result){...})
    .onError(function(result){...})

Now this by itself isn’t anything particularly special, but it’s the new advancements for Futures and Promises in Scala 2.10 that got me interested in them.

Composability

The big thing that I want to highlight is composability. Composability in terms of Futures is that you can put them together like little building blocks in a way that makes things much easier.

Here’s an example of how composable futures will make life easier. Let’s say I want to make an HTTP request to some URL, and the response will be another URL to which I will need to make a new request.

Let’s see what that looks like without composability (Javascript-style).

function handleError(err){...}
function handleSuccess(result){...}

makeHttpRequest(url, function(response, err){
    if(err){
        handleError(err)
        return
    } else {
        var nextUrl = ... //from the response
        makeHttpRequest(nextUrl, function(resp2, err2){
            if(err2){
                handleError(err)
                return
            } else {
                handleSuccess(resp2)
            }
        })
    }
})

Wow is that ugly! It gets nested four tabs deep, and the error handling needs to get pushed in at every step. Now let’s see a composable version of the same code, as written in Scala.

//assume that our http request function returns a Future
def makeHttpRequest(url: String): Future[Response]

val result = for{
    resp <- makeHttpRequest(url)
    resp2 <- makeHttpRequest(getUrl(resp))
} yield resp2

result onComplete {
    case Failure(exception) => handleFailure(exception)
    case Success(result) => handleResult(result)
}

This looks much cleaner to me! Chaining the calculations together is done in 4 lines, and is separate from the handling of the results. Thanks to Scala’s syntax sugar for for-comprehensions, you could chain a whole bunch of asynchronous calculations together without needing to indent any further than one tab.

Another nice thing is that errors are automatically “trickled down”, so that if the first call to makeHttpRequest throws an exception, the second call will never happen, and that exception will be wrapped in a Failure to be handled in the onComplete block.

So to summarize, using Futures helps you handle chaining of operations while managing exceptions.

Implementing Code with Futures

Scala gives you two convenient ways to create a Future. The easiest way is to use

import scala.concurrent.Future
import scala.concurrent.ExecutionContext.Implicits.global

val futureResult = Future {
    //Do whatever stuff you need to be asynchronous here.
    //Any thrown exceptions will be wrapped in the result
}

Scala will use the global ExecutionContext to run the body of your Future{...} on another thread, and manage its lifecycle. Any exceptions thrown within the Future’s body will be wrapped up in the Future’s result.

The other way to make a Future is to use a Promise. Promises are like the ‘write’ side of the Future’s ‘read’. You can use Promises to convert callback-style code into futures-style, or you could use them in classes to handle variables that get initialized late.

//converting callback-style code
def makeHttpRequest(url: String): Future[Response] = {
    val p = Promise[Response]()
    makeHttpRequestWithCallback(url,
        (result) => p.success(result), //success callback
        (e) => p.failure(e) //error callback
    )
    p.future
}

As you can see, the Promise can be completed in either a ‘success’ or ‘failure’ state, corresponding to results and exceptions. Another important detail is that it can only be completed once. Fortunately, Scala 2.10’s Promise API gives you a trySuccess and tryFailure that will simply return false instead of throwing an exception if you use it more than once.

class A {
    private val p = Promise[X]()
    def x: Future[X] = p.future

    def prepare: Unit = p.trySuccess(someXValue)
}

val a = new A
a.x onSuccess {
    case xValue => println("got the x value")
}

a.prepare
// this causes the `a.x` to complete, triggering the onSuccess callback
//prints 'got the x value'

There are a bunch of convenience methods that you can use with Futures and Promises. So check them out in the Scala 2.10 API.