A Future is a sort of a placeholder object that you can create for a result that does not yet exist.
Generally, the result of the Future is computed concurrently and can be later collected.
A Future is an object holding a value which may become available at some point. This value is usually the result of some other computation.This value is usually the result of some other computation:
If the computation has not yet completed, we say that the Future is not completed.
If the computation has completed with a value or with an exception, we say that the Future is completed.
Completion can take one of two forms:
When a Future is completed with a value, we say that the Future was successfully completed with that value.
When a Future is completed with an exception thrown by the computation, we say that the Future was failed with that exception.
Creating Futures
val session = socialNetwork.createSessionFor("user", credentials)
val f = Future[List[Friend]] = future {
session.getFriends()
}
future method creates a Future object
Future[T] is a type expression for a Future instantiated with type T
Attaching Callbacks to Future object
import scala.util.{Success, Failure}
val f: Future[List[String]] = future {
session.getRecentPosts
}
f onComplete {
case Success(posts) => for (post <- posts) println(post)
case Failure(t) => println("An error has occured: " + t.getMessage)
}
onComplete, onSuccess, onFailure are three callbacks that can be attached to a future object.
Blocking
import scala.concurrent._
import scala.concurrent.duration._
def main(args: Array[String]) {
val rateQuote = future {
connection.getCurrentValue(USD)
}
val purchase = rateQuote map { quote =>
if (isProfitable(quote)) connection.buy(amount, quote)
else throw new Exception("not profitable")
}
Await.result(purchase, 0 nanos)
}
Exceptions
Promises
import scala.concurrent.{ future, promise }
import scala.concurrent.ExecutionContext.Implicits.global
val p = promise[T] // create a promise
val f = p.future // obtain the Future p completes
val producer = future { // first async computation
val r = produceSomething() // produces value r
if (isValid(r))
p success r // (successfully) fulfill p with r
else {
q = doSomeMoreComputation(r);
p success q
}
}
val consumer = future { // second async computation
startDoingSomething()
f onSuccess { // reactor on f
case r => doSomethingWithResult()
}
}
While futures are defined as a type of read-only placeholder object created for a result which doesn’t yet exist, a promise can be thought of as a writable, single-assignment container, which completes a future.
That is, a promise can be used to successfully complete a future with a value (by “completing” the promise) using the success method. Conversely, a promise can also be used to complete a future with an exception, by failing the promise, using the failure method.
A promisep completes the future returned by p.future. This future is specific to the promise p.
producer-consumer example: one computation produces a value and hands it off to another computation which consumes that value. The passing of the value is done using a promise.