43 Future - Get Programming With Scala
43 Future - Get Programming With Scala
In the previous lesson, have learned about implicit parameters and val-
ues; you’ll now see them in action when defining an instance of type
Future . You’ll discover the difference between synchronous and asyn-
chronous computations and how they can affect your program’s perfor-
mance. You’ll see how you can use the type Future to define asyn-
chronous computations that can fail. An operation is asynchronous if
your program can continue to run without waiting for its outcome. You’ll
also process its result once completed. In the capstone, you’ll use the type
Future to read and write data to a database asynchronously for your
quiz application.
Consider this
Imagine you are developing a program to handle orders for a store. You
need to confirm a product’s availability with its warehouse via an HTTP
API, a known bottleneck of your application. You can perform it asyn-
chronously using Future to improve its overall performance.
import scala.concurrent.Future
import scala.concurrent.ExecutionContext.Implicits.global
package scala.concurrent
object Future {
First, include the companion object Future in your scope by adding im‐
port scala.concurrent.Future . Then, invoke its method
Future.apply by providing the instructions to execute asynchronously
and with an execution context. Figure 43.1 compares the signature of
Try.apply with Future.apply . The two methods look very similar.
However, Future.apply requires an extra implicit parameter of type
ExecutionContext , which provides information that makes the asyn-
chronous computation possible.
Figure 43.1 A comparison between the apply method for Try and
Future . The first represents synchronous computations that can fail, the
second asynchronous ones. They both delay the execution of an expres-
sion. However, the Future one requires an instance of
ExecutionContext , which contains information about the resources
and execution strategy.
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.ExecutionContext
using val ec = ExecutionContext.global
Let’s see a few more examples of how you can use the method
Future.apply :
scala> Future(10/2)
error: Cannot find an implicit ExecutionContext. You might pass
an (using ec: ExecutionContext) parameter to your method
or import scala.concurrent.ExecutionContext.Implicits.global.
Future(10/2)
^
// You need to provide an ExecutionContext to Future.apply!
scala> Future(10/2)
val res0: scala.concurrent.Future[Int] = Future(Success(5))
// Its execution has completed with success
// before the REPL displays its content
scala> tenOverZero
val tenOverZero: scala.concurrent.Future[Int] = Future(Failure(java.lang.ArithmeticExcept
// Checking its content again after some time,
// it has completed with a failure
import scala.concurrent.Future
import scala.concurrent.ExecutionContext.Implicits.global
Consider your program to place orders in a store. Suppose that the third-
party API can provide information on the quantity available for a certain
product. You want to keep track of it to help the store decide on the items
to restock.
import scala.concurrent.Future
import scala.util.{Failure, Success}
import scala.concurrent.ExecutionContext.Implicits.global
You can use pattern matching on many of the types you have encoun-
tered; unfortunately, Future is not one of them. A pattern-matching op-
eration is synchronous as it requires the value wrapped inside your type
to be available. For an instance of Future[T] , the method onComplete
allows you to execute a function once completed:
The function onComplete returns a value of type Unit . Any result that
your callback function f produces will be lost. If you need to retain its
result, you should consider using its method map instead. You’ll learn
more about this in the next lesson. A few more examples of how to use
the method onComplete are the following:
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.Future
Summary
TRY THIS The following snippet of code prints all the files in the cur-
rent directory to the terminal. Change its code to execute it
asynchronously.
import java.io.File
new File(".").listFiles().foreach(println)
scala> test()
abc012
scala> test()
0abc12
scala> test()
012abc
scala> isSuccess(Future("hello"))