【问题标题】:Sequentially combine arbitrary number of futures in Scala在Scala中顺序组合任意数量的期货
【发布时间】:2012-11-29 23:28:25
【问题描述】:

我是 scala 的新手,我尝试在 scala 2.10RC3 中结合几个 Futures。 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) }

【问题讨论】:

    标签: scala concurrency future


    【解决方案1】:

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

    使用地图:

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

    【讨论】:

    • 谢谢!这正是我所需要的。
    【解决方案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文章。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-08-21
      • 1970-01-01
      • 1970-01-01
      • 2016-05-02
      • 2018-06-13
      • 1970-01-01
      相关资源
      最近更新 更多