🎓 A1Learner
🔍
0 of 48 lessons completed

Scala Future Sequencing

Future sequencing turns a list of Futures into one Future of a list. It waits for every job and keeps the results in the same order as the list.

Sequence turns a list of Futures into one Future

Three Futures become one Future holding a list. Awaiting it gives the list in order.

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

@main def main(): Unit =
  val jobs = List(Future { 1 }, Future { 2 }, Future { 3 })
  val combined = Future.sequence(jobs)
  val result = Await.result(combined, 5.seconds)
  println(result)

Traverse maps and sequences in one step

Each number is mapped to a Future ten times as large. The combined list holds 10, 20, and 30.

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

@main def main(): Unit =
  val combined = Future.traverse(List(1, 2, 3))(x => Future { x * 10 })
  val result = Await.result(combined, 5.seconds)
  println(result)

A sequenced list is an ordinary list

Once awaited, the list can be used like any list. Its sum here is 9.

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

@main def main(): Unit =
  val combined = Future.sequence(List(Future { 2 }, Future { 3 }, Future { 4 }))
  val results = Await.result(combined, 5.seconds)
  println(results.sum)

Example

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

@main def main(): Unit =
  val combined = Future.traverse(List(10, 20, 30))(x => Future { x + 5 })
  val totals = Await.result(combined, 5.seconds)
  println(totals)
  println(totals.sum)

Key points

  • Sequence: Future.sequence turns a list of Futures into one Future of a list.
  • Order: the results stay in list order, matching the order of the input list.
  • Traverse: Future.traverse maps each item to a Future and then sequences the results.
  • Wait once: Await waits once on the combined Future, not on each job.
  • Empty: sequencing an empty list gives an empty list.

In this example, traverse adds 5 to each price and sequences the three Futures into one. The awaited list is printed, then its sum 75 is printed.

Note

if any Future in the list fails, the sequenced Future fails too.

Try it Yourself

Edit the code, then press Run.

Running is simulated · Scastie

Exercise

What does Future.sequence do?