在Scala中按顺序组合任意数量的期货

时间:2012-12-12 09:34:45

标签: scala concurrency future

我是scala的新手,我尝试在scala 2.10RC3中组合几个Futures。 Futures应按顺序执行。在文档Scala SIP14中,定义方法andThen以便按顺序执行期货。我用这种方法组合了几个Futures(参见下面的例子)。我的期望是它打印6但实际上结果是0。我在这做错了什么?我有两个问题:

首先,为什么结果为0。其次,我如何组合多个Futures,以便在第一个Future完成之前不会开始执行第二个Future

val intList = List(1, 2, 3)

val sumOfIntFuture = intList.foldLeft(Future { 0 }) {
 case (future, i) => future andThen {
  case Success(result) => result + i 
  case Failure(e) => println(e)
 }
}

sumOfIntFuture onSuccess { case x => println(x) }

2 个答案:

答案 0 :(得分:12)

andThen用于副作用。它允许您指定在将来完成之后以及用于其他操作之前要执行的某些操作。

使用地图:

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

答案 1 :(得分:2)

我喜欢这种通用方法:

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)

}

然后混合上面的特性并像这样使用它:

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

可以改进此代码以保留输入集合类型。例如,请参阅this文章。