Sequentially combine arbitrary number of futures in Scala

∥☆過路亽.° 提交于 2019-12-05 02:38:27

andThen is for side-effects. It allows you to specify some actions to do after future is completed and before it used for something else.

Use map:

scala> List(1, 2, 3).foldLeft(Future { 0 }) {
     |  case (future, i) => future map { _ + i }
     | } onSuccess { case x => println(x) }
6

I like this generic approach:

trait FutureImplicits {

  class SeriallyPimp[T, V](futures: Seq[T]) {
    def serially(f: T => Future[V])(implicit ec: ExecutionContext): Future[Seq[V]] = {
      val buf = ListBuffer.empty[V]
      buf.sizeHint(futures.size)

      futures.foldLeft(Future.successful(buf)) { (previousFuture, next) =>
        for {
          previousResults <- previousFuture
          nextResult <- f(next)
        } yield previousResults += nextResult
      }
    }
  }

  implicit def toSeriallyPimp[T, V](xs: Seq[T]): SeriallyPimp[T, V] =
    new SeriallyPimp(xs)

}

Then mix-in the above trait and use it like this:

val elems: Seq[Elem] = ???
val save: Elem => Future[Result] = ???
val f: Future[Seq[Result]] = elems serially save

This code could be improved to preserve the input collection type. See this article for example.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!