Tv-Wonders
Tv-Wonders

Reputation: 5

Scala - How to call a future function while mapping over a Seq?

I have a Seq[String], and these string values are needed to call another function defined as:

def getSomethingById(id: String): Future[Someting]

I'm trying to create a function which takes the Seq[String] and returns Future[Seq[Something]]; i.e.,

def getSomethings(ids: Seq[String]): Future[Seq[Something]]

The only way to get the Something type is by calling the getSomethingById method above.

Is there a way I can map over the Seq[String], then call getSomethingById?

Upvotes: 0

Views: 273

Answers (2)

Puneeth Reddy V
Puneeth Reddy V

Reputation: 1568

In addition to existing answer you can also use Future.traverse which is very similar

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


def getSomethingById(id: String): Future[String] = Future{
  id + "from Something Id"
}

def getSomethings(ids: Seq[String]): Future[Seq[String]] = 
       Future.traverse(ids)(getSomethingById)

scala> getSomethingById: (id: String)scala.concurrent.Future[String]
scala> getSomethings: (ids: Seq[String])scala.concurrent.Future[Seq[String]]

Test

scala> getSomethings(Range.apply(1,3).map(_.toString))
res0: Vector(1from Something Id, 2from Something Id)

Upvotes: 0

Tom
Tom

Reputation: 2254

You can use Future.sequence for this:

def getSomethings(ids: Seq[String]): Future[Seq[Something]] =
  Future.sequence(ids.map(getSomethingById))

https://www.scala-lang.org/api/current/scala/concurrent/Future%24.html

Simple version of Future.traverse. Asynchronously and non-blockingly transforms a TraversableOnce[Future[A]] into a Future[TraversableOnce[A]]. Useful for reducing many Futures into a single Future.

Upvotes: 4

Related Questions