# Futures and Asynchronous Code — Scala

Source: https://www.geekswithgeeks.com/en/scala/k-futures

> Run asynchronous computations with Future and compose them.

## Futures in the standard library

A **`Future[A]`** represents a value that will be available later, computed on an **`ExecutionContext`** (a thread pool). `Future { ... }` starts running immediately, which is called **eager** evaluation. Futures compose with `map`, `flatMap`, `recover`, `recoverWith` and **for comprehensions**, so dependent asynchronous steps read sequentially, while `Future.sequence` and `Future.traverse` run many in parallel and collect results. Callbacks such as `onComplete` exist, but composing is cleaner. A subtle point: in a for comprehension, futures are created when their line runs, so to run two independent futures **in parallel**, create them **before** the `for`. Blocking with `Await.result` is for tests and program edges only; in services, return the `Future` to the framework. Blocking I/O inside the global execution context should be wrapped in `blocking { ... }` or run on a dedicated pool. Because Futures are eager and memoised, they are not referentially transparent, which is one reason many teams use **effect systems** (next topic) instead.

## Composing Futures

Independent futures run in parallel and are combined when both finish.

![Two parallel lanes with progress bars starting at the same time, merging into a single result box at the end.](assets/figures/scala/section-6-map.svg) — Figure 6.1 — Parallel futures joined by a for comprehension.

## Parallel and sequential Futures

Start independent work first, then combine with for.

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

case class Customer(id: String, name: String)
case class Order(id: String, totalPaise: Long)

def fetchCustomer(id: String): Future[Customer] = Future { Thread.sleep(200); Customer(id, "Asha") }
def fetchOrders(id: String): Future[List[Order]] = Future { Thread.sleep(200); List(Order("o1", 120000)) }

def dashboard(id: String): Future[String] =
  val customerF = fetchCustomer(id)        // both start now, in parallel
  val ordersF = fetchOrders(id)
  for
    customer <- customerF
    orders   <- ordersF
  yield s"${customer.name}: ${orders.size} orders, total ${orders.map(_.totalPaise).sum} paise"

val safe: Future[String] = dashboard("c-1").recover { case e: Exception => s"unavailable: ${e.getMessage}" }

val all: Future[List[Customer]] = Future.traverse(List("c-1", "c-2", "c-3"))(fetchCustomer)

@main def runDashboard(): Unit =
  println(Await.result(safe, 2.seconds))   // blocking is acceptable only at the program edge
  println(Await.result(all, 2.seconds).map(_.name))
```

## Create futures before the for

Writing `for a <- fetchA(); b <- fetchB() yield ...` runs the calls one after the other, because fetchB is only called after fetchA completes. Assign both futures to vals first to run them in parallel.

**Quiz:** In a for comprehension over Futures, how do you make two independent calls run in parallel?

- [ ] Use two separate for loops
- [ ] Use Await.result inside the for
- [x] Start both futures (assign them to vals) before the for comprehension
- [ ] It always runs in parallel

*Answer:* Start both futures (assign them to vals) before the for comprehension. Futures start when created, so creating them first lets them run concurrently.
