10

我是 scala 的新手,我尝试在 scala 2.10RC3 中结合几个期货。Futures应该按顺序执行。在文档Scala SIP14中定义了该方法andThen,以便按顺序执行 Futures。我用这种方法组合了几个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) }
4

2 回答 2

12

andThen是为了副作用。它允许您指定在 future 完成之后以及在它用于其他事情之前要执行的一些操作。

使用地图:

scala> List(1, 2, 3).foldLeft(Future { 0 }) {
     |  case (future, i) => future map { _ + i }
     | } onSuccess { case x => println(x) }
6
于 2012-12-12T10:14:21.277 回答
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

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

于 2015-01-30T10:49:40.737 回答