Search code examples
scalasequencefuturescala-option

how to combine the results Future[ Option[ T ] ] into Seq[ T ]


I have a method

 def readTree(id: String): Future[Option[CategoryTreeResponse]]

and a list of String channels:List[String].

How to iterate and combine all the results into a non Future Sequence ? such as :

 def readAllTrees(): Seq[CategoryTreeResponse] =  ???

Possibly without blocking.

Coming form the imperative world, I'd do like this :

import scala.concurrent.duration._

def readTrees(): Seq[CategoryTreeResponse] = {
  val list = ListBuffer[CategoryTreeResponse]()
  for (id <- channels) {
    val tree = Await.result(readTree(id), 5.seconds)
    if (tree.isDefined) {
      list += tree.get
    }
  }
  list
}

Solution

  • You could do something like this

    def readAllTrees(channels: List[String]): Future[Seq[CategoryTreeResponse]] = {
        Future.sequence(channels.map(readTree(_))).map(_.flatten)
    }
    

    I have changed the signature of readAllTrees to receive the list and return a Future of the Sequence.

    If you want to access to the resulting sequence you will need to wait until is finished doing

     Await.result(readAllTrees(channels), Duration.Inf)
    

    But this is not a very nice way to manage futures because it will lock the thread that calls Await.ready