How to get Future[Seq[Person]] instead of Seq[Future[Person]]
Asked Answered
M

3

9

I have two external call which

  1. Which gives Future[Seq[People]]
  2. Which takes person_id and returns person_status as Future[String]

I need to update each person status using second call from the sequence available in first call. This is how I tried,

getFuturePeople.map( (seqPeople : Seq[People]) => {
     seqPeople.map(person => getStatus(person._id).status).map(status => {
     //Update status for this person but I get Seq[Future[Peoson]]
   }) 
})
Margherita answered 31/7, 2018 at 5:56 Comment(3)
Possible duplicate of How to flatten a List of Futures in ScalaUnequivocal
@Unequivocal That question asks how to get a List[A], not a Future[List[A]]. That the answer happens to be similar is immaterial.Destroy
@BrianMcCutchon I don't fully agree that the questions don't qualify as duplicates, but ok sure, take one of the other countless questions that ask for sequence...Unequivocal
B
30

Use can use Future.sequence to transform the result, eg:

val futureOfSeq = Future.sequence(seqOfFuture)

Brash answered 31/7, 2018 at 6:0 Comment(0)
D
5

you need to traverse on List as Future.traverse.

Example,

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

def getFuturePeople = Future { List("Steven", "Wilson", "Michael") }
def getStatus(name: String) = Future { s"$name updated" }

Now, like what you tried, you get Future[List[Future[String]]].

getFuturePeople.map { people => people.map { p => getStatus(p) } }

1) So, instead of just mapping on list of people, do Future.traverse,

val updatedPeople: Future[List[String]] = getFuturePeople.flatMap { people =>
       Future.traverse(people) { p =>
         getStatus(p)
       }
 }

2) What also works is once you map on list of people and get List[Future[A]], use Future.sequence to convert to Future[List[A]],

val updatedPeopleUsingSeq: Future[List[String]] = getFuturePeople.flatMap { people =>
       Future.sequence {
         people.map(getStatus)
       }
}
Dispense answered 31/7, 2018 at 6:14 Comment(2)
This has the right information, but it is so verbose that it is hard to see it and I nearly didn't bother reading it all. REPL output is hard to read and you don't really need to show your working like this, you can just show the solution with a couple of lines of explanation.Jacy
It is also better if you use the same types and names as the original question where possible. (e.g. Seq rather than List, getFuturePeople rather than getPeople)Jacy
O
0

use Future.sequence like this:

val returnedFuture :Seq[Future[People]] = Seq(Future.successful(People))

val flattenedFuture:Future[Seq[Peope]] = Future.sequence(returnedFuture)
Outthink answered 31/7, 2018 at 10:16 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.