Jonna
Jonna

Reputation: 1645

Executing sequence of functions that return a future sequentially

I have a sequence of functions that return a future. I want to execute them sequentially i.e. after the first function future is complete, execute the next function and so on. Is there a way to do it?

ops: Seq[() => Future[Unit]]

Upvotes: 1

Views: 1859

Answers (3)

Laurence Bird
Laurence Bird

Reputation: 180

If given a Seq[Future[T]] you can convert it to a Future[Seq[T]] like so:

Val a: Seq[Future[T]] = ???

val resut: Future[Seq[T]] = Future.sequence(a)

a little less boilerplate than the above :)

Upvotes: 2

Kolmar
Kolmar

Reputation: 14224

You can combine all the futures into a single one with a foldLeft and flatMap:

def executeSequentially(ops: Seq[() => Future[Unit]])(
  implicit exec: ExecutionContext
): Future[Unit] =
  ops.foldLeft(Future.successful(()))((cur, next) => cur.flatMap(_ => next()))

foldLeft ensures the order from left to right and flatMap gives sequential execution. Functions are executed with the ExecutionContext, so calling executeSequentially is not blocking. And you can add callbacks or await on the resulting Future when/if you need it.

If you are using Twitter Futures, then I guess you won't need to pass ExecutionContext, but the general idea with foldLeft and flatMap should still work.

Upvotes: 4

Tzach Zohar
Tzach Zohar

Reputation: 37852

I believe this should do it:

import scala.concurrent.{Await, Future}
import scala.concurrent.duration.Duration

def runSequentially(ops: Seq[() => Future[Unit]]): Unit = {
  ops.foreach(f => Await.result(f(), Duration.Inf))
}

If you want to wait less then Duration.Inf, or stop at failure - should be easy to do.

Upvotes: 0

Related Questions