Sonia Fernández Rodríguez
Software Engineer
def parseURL(url: String): Try[URL] = Try(new URL(url))
val result = parseURL("http://www.hotels.com")
result match {
case Success(url) => println(url)
case Failure(ex) => println(s"An error occurred: ${ex.getMessage}")
}
package scala.concurrent
https://blog.knoldus.com/2016/07/01/getting-asynchronous-in-scala-part-1-future-callbacks-combinators-etc/
object Future {
def apply[T](body: =>T)(implicit executor: ExecutionContext): Future[T]
}
import scala.concurrent.ExecutionContext.Implicits.global
Future { /* do something */ }(ExecutionContext.global)
Future()
Creates a Future for an asynchronous computation
Uses the executor => body will be executed in a different thread
object Future {
def apply[T](body: =>T)(implicit executor: ExecutionContext): Future[T]
}
import scala.concurrent.Future
import scala.concurrent.ExecutionContext.Implicits.global
def getStudents(courseName: String): Future[List[String]] = Future {
codeAcademyService.getStudents(courseName)
}
object Future {
def failed[T](exception: Throwable): Future[T]
def successful[T](result: T): Future[T]
}
Future.failed(new RuntimeException("I will fail"))
Future.successful("Successful value")
Create futures that doesn't need thread-switching
def onComplete[U](f: Try[T] => U)(implicit executor: ExecutionContext): Unit
import scala.util.{Failure, Success}
val eventualStudents = getStudents("Scala4JavaDevs")
eventualStudents.onComplete {
case Success(students) => for(student <- students) println(student)
case Failure(exception) => println(exception.getMessage)
}
Example
import scala.concurrent.Await
import concurrent.duration._
Await.result(result, 1.second)
def result[T](awaitable: Awaitable[T], atMost: Duration): T
Example
def map[S](f: T => S)(implicit executor: ExecutionContext): Future[S]
def flatMap[S](f: T => Future[S])(implicit executor: ExecutionContext): Future[S]
getStudents("Scala4JavaDevs").map { students =>
students.filter(name => name.startsWith("R"))
}
Examples
def companiesByEmployees(employeeNames: List[String]): Future[List[String]] = Future {
employeeServiceApi.getCompanyNames(employeeNames)
}
getStudents("Scala4JavaDevs").flatMap { students =>
companyByEmployee(students)
}
for {
students <- getStudents("Scala4JavaDevs")
companies <- companiesByEmployees(students)
companiesAddress <- asyncService.getCompanyAddressses(companies)
// ... all sequential futures we want to do
} yield companiesAddress
val eventualTopStudent: Future[String] = service.getTopStudent
val eventualTopCompany: Future[String] = service.getTopCompany
val result: Future[String] =
for {
student <- eventualTopStudent
company <- eventualTopCompany
} yield s"Top student: $student, Top company: $company"
Example
// Parallel code
def operation(op: String) = Future {
Thread.sleep(400)
println(s"$op operation")
}
val asyncTask1 = operation("First")
val asyncTask2 = operation("Second")
val allCalls: Future[Unit] = for {
result1 <- asyncTask1
result2 <- asyncTask2
} yield println("Finished")
Await.result(allCalls, 3.second)
// Sequential code
def operation(op: String) = Future {
Thread.sleep(400)
println(s"$op operation")
}
val allCalls: Future[Unit] = for {
result1 <- operation("First")
result2 <- operation("Second")
} yield println("Finished")
Await.result(allCalls, 3.second)
// Expected output
First operation
Second operation
Finished
// Expected output - Non-deterministic
// Output 1
First operation
Second operation
Finished
// Output 2
Second operation
First operation
Finished
cd path/to/scala-for-java-devs
git stash
git pull
git checkout lesson7
./sbt test
Your feedback is highly appreciated :-)
By Sonia Fernández Rodríguez