Scala Futures: How to Use

scala
Reading Time: 3 minutes

Scala Future gives you a simple way to run an algorithm concurrently.

Scala Future: Run and Block

By following this approach, first create a future and then block to wait for its result.

import scala.concurrent.{Await, Future}
import scala.concurrent.duration._
import scala.concurrent.ExecutionContext.Implicits.global

object ScalaFuture extends App {

  //creating future
  val f = Future {
      sleep(500)
      "Hello" + "Vipul"
  }

  val response = Await.result(f, 1 second)  // Blocking
  println(response)
  sleep(1000)

}

Future and ExecutionContext

A Future[T] is a container that runs a computation concurrently, and at some future time may return either (a) a result of type T or (b) an exception.

The result of the computation becomes available once the future completes.

  • An ExecutionContext executes a task it’s given. You can think of it as being like a thread pool.
  • The ExecutionContext.Implicits.global import statement shown in the examples imports the default global execution context.

When we are using Future we must use ExecutionContext.global, making it available using a single import:

import scala.concurrent.ExecutionContext.Implicits.global

The first method for working with Future functionally is map.

If we want to demonstrate Future in simple way then we can generate a Future Response in given way:

import java.util.UUID
def getRandomUUID() : UUID = {
  Thread.sleep(3000L)
  UUID.randomUUID()
}
val generatedUUID: Future[UUID] = Future {
  getRandomUUID()
}

When we call Future.apply with the call to getRandomUUID inside, the Future runtime executes it on another thread. It might look like we were passing the result of invoking the method to the Future, however, Future.apply takes it as a by-name parameter. It moves evaluation into a thread provided by implicit ExecutionContext.

CallBack

onComplete():

val results: Future[List[Tag]] = Tags.all.toList
results onComplete {
case Success(list) => //do something with list
case Failure(t) => //throw the error
}

onComplete returns Unit, it allows you to do something with the Future result, but it won’t return a value.

Transform Future

map:

def map[B](f: A => B): Option[B]

When we have a Future instance, we can use the map method to transform its successful result without blocking the main thread:

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

val numF = Future{ 3 }

val stringF = numF.map(n => Future(n.toString))

flatMap:

def flatMap[B](f: A => Option[B]): Option[B]

flatMap allow you do something with the list and return a new Future.

val finalFuture = results
 .flatMap(x => /* do something and return a future */)
 .flatMap(y => /* do something else and return a future */)
 .flatMap(z => /* do something else and return a future */)
 .map(myresult => /* do something */)

If something goes wrong along the way, the chain is broken early and you’ll get the first error occurred.

This allows for an even nicer syntax

val finalFuture = for {
    x <- results
    y <- /* do something and return a future */
    z <- /* do something and return a future */
 } yield something(z)

transform:

As opposed to the map() function, we can map both successful and failed cases with the transform(f: Try[T] => Try[S]) function:

val future = ... // Future[T]
val mapped = future.transform {
  case Success(_) => Success("OK")
  case Failure(_) => Success("KO")
}

Combine futures

zip:

def futureA = Future { "A" }
def futureB = Future { "B" }
def futureC = Future { "C" }

f1.zip(f2).zip(f3).map{
      case ((f11,f22),f33) => (f11,f22,f33)
    }

lazyZip:

If we want to combine the results of two independent variables into one, then we should use the lazyZip method:

val listOne = List(1, 2, 3, 4, 5)
val listTwo = List(2, 3, 4, 5, 6)
val sumOf = (listOne lazyZip listTwo).map((m, o) => m+o)
print(fruits)

Results => List(3,5,7,9,11)

Conclusion

Here we discussed Future API, and how we can use Future and available functions.

footer

Written by 

Vipul Kumar is Senior Software Consultant having 6years of experience. He has knowledge of languages like Functional Java, Scala, Akka, Akka-http. He is familiar with Object-Oriented Programming Paradigms and also has an interest in Functional Programming technologies. His hobbies include travelling, riding bikes and listening to music.

Discover more from Knoldus Blogs

Subscribe now to keep reading and get access to the full archive.

Continue reading