futures

Placeholder object for value that may not yet exist, revolve around ExecutionContext which has access to a thread pool similar to Executor design pattern, commonly you map over it

val futureHttpResult = WS.url(“http://catpictures.dev/top10”).get()
val webPage = futureHttpResult.map { catPicturesHttpBody =>
  val parsed = parse(catPicturesHttpBody)
  val firstPictureUrl = parsed.get(0)
  Ok(myWebPageTemplate(firstPictureUrl))
}
webPage

Nonblocking Looks sequential, but when it does load inner map block runs

Promises like syntax

val fut1: Future[Assignment] = Future(nextAssignmentStore.get(classId1))
val fut2: Future[Assignment] = Future(nextAssignmentStore.get(classId2))
val fut3: Future[Assignment] = Future(nextAssignmentStore.get(classId3))
val allFutures: List[Future[Assignment]] = List(fut1, fut2, fut3)

Need Future[List[]] instead of List[Future[]]

then runs when all complete

val allResults: Future[List[Assignment]] = Future.sequence(allFutures)
allResults.map { results =>
  Result(results, paging = None)
}

Defining

// delegate the execution of fatMatrix.inverse() to an ExecutionContext and embody the result of the computation in inverseFuture.

val inverseFuture: Future[Matrix] = Future {
  fatMatrix.inverse() // non-blocking long lasting computation
}(executionContext)

implicit val ec: ExecutionContext = ...
val inverseFuture : Future[Matrix] = Future {
  fatMatrix.inverse()
} // ec is implicitly passed

Defining Global Execution Context

//1
import scala.concurrent.ExecutionContext.Implicits.global
//2
implicit val executor =  scala.concurrent.ExecutionContext.global
//3
Future { /* do something */ }(executor)

States

not yet completed, not completed

completed with value or exception, completed

  • failed with exception or successfully completed with value

Immutable after it becomes completed

Callbacks

f onComplete {
  case Success(posts) => for (post <- posts) println(post)
  case Failure(t) => println("An error has occurred: " + t.getMessage)
}

Callback takes a Try[T] => U where Try[T] is like an option but contains either the variable or an exception

Combinators

Only Success (foreach)

f foreach { posts =>
  for (post <- posts) println(post)
}

Change Future Value (map)

val rateQuote = Future {
  connection.getCurrentValue(USD)
}

val purchase = rateQuote map { quote =>
  if (isProfitable(quote)) connection.buy(amount, quote)
  else throw new Exception("not profitable")
}

purchase foreach { _ =>
  println("Purchased " + amount + " USD")
}

exception are propagated

For comprehensions(flatmap & withfilter)

flatmap -> like map but ft returns a future not a value, used to call ft's that return future on value yet to be computed

for loop basically allows several flatMaps then a final map yielding a Future value

futures start running immediately on seperate threads and main thread runs through this without blocking

resultF is just a Future that waits for component parts to finish before completing itself

val threeF = Future(3)
val fourF = Future(4)
val fiveF = Future(5)

val resultF = for{
  three <- threeF
  four <- fourF
  five <- fiveF
}yield{
  three * four * five
}

//EQUALS

val resultF = threeF.flatMap(three => fourF.flatMap(four => fiveF.map(five => three * four * five)))

Example 2

val usdQuote = Future { connection.getCurrentValue(USD) }
val chfQuote = Future { connection.getCurrentValue(CHF) }

val purchase = for {
  usd <- usdQuote
  chf <- chfQuote
  if isProfitable(usd, chf)
} yield connection.buy(amount, chf)

purchase foreach { _ =>
  println("Purchased " + amount + " CHF")
}

//EQUALS

val purchase = usdQuote flatMap {
  usd =>
  chfQuote
    .withFilter(chf => isProfitable(usd, chf)) //throws exception in future if bool false
    .map(chf => connection.buy(amount, chf))
}

Exception recovery

  • recover

  • RecoverWith

  • fallbackTo

Coursera Usage

future.flatMap(x =>

x

...

y.flatMap( t =>

    t

)

)

is the same as

x <- future

Thread blocks while the future waits to finish and collapse

y <- x

Last updated