1
votes

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]]

3

3 Answers

4
votes

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.

2
votes

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 :)

0
votes

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.