Scala等待期货序列 [英] Scala waiting for sequence of futures

查看:56
本文介绍了Scala等待期货序列的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我希望像下面这样的代码可以等待两种期货,但事实并非如此.

I was hoping code like follows would wait for both futures, but it does not.

object Fiddle {
  val f1 = Future {
    throw new Throwable("baaa") // emulating a future that bumped into an exception
  }

  val f2 = Future {
    Thread.sleep(3000L) // emulating a future that takes a bit longer to complete
    2
  }

  val lf = List(f1, f2) // in the general case, this would be a dynamically sized list

  val seq = Future.sequence(lf) 

  seq.onComplete {
    _ => lf.foreach(f => println(f.isCompleted))
  }
}

val a = FuturesSequence

我以为seq.onComplete会等到它们全部完成才完成本身,但事实并非如此.结果为:

I assumed seq.onComplete would wait for them all to complete before completing itself, but not so; it results in:

true
false

在scala.concurrent.Future的源代码中,

.sequence有点难以理解,我想知道如何实现一个并行处理,以等待(动态大小的)序列的所有原始将来,否则可能是问题所在在这里.

.sequence was a bit hard to follow in the source of scala.concurrent.Future, I wonder how I would implement a parallel that waits for all original futures of a (dynamically sized) sequence, or what might be the problem here.

相关问题:推荐答案

等待所有结果(失败与否)的一种常用方法是将失败提升"到未来内部的新表示中,以便所有未来都完成一些结果(尽管它们可能会以表示故障的结果来完成).一种自然的获取方法是提升到Try.

One common approach to waiting for all results (failed or not) is to "lift" failures into a new representation inside the future, so that all futures complete with some result (although they may complete with a result that represents failure). One natural way to get that is lifting to a Try.

Twitter对期货的实施提供了方法,使它变得微不足道,但是您可以对标准库的实现执行类似的操作:

Twitter's implementation of futures provides a liftToTry method that makes this trivial, but you can do something similar with the standard library's implementation:

import scala.util.{ Failure, Success, Try }

val lifted: List[Future[Try[Int]]] = List(f1, f2).map(
  _.map(Success(_)).recover { case t => Failure(t) }
)

现在Future.sequence(lifted)将在每个将来完成时完成,并且将代表使用Try的成功和失败.

Now Future.sequence(lifted) will be completed when every future is completed, and will represent successes and failures using Try.

因此,假设执行上下文当然隐式可用,则用于等待一系列期货的所有原始期货的通用解决方案可能如下所示.

And so, a generic solution for waiting on all original futures of a sequence of futures may look as follows, assuming an execution context is of course implicitly available.

  import scala.util.{ Failure, Success, Try }

  private def lift[T](futures: Seq[Future[T]]) = 
    futures.map(_.map { Success(_) }.recover { case t => Failure(t) })

  def waitAll[T](futures: Seq[Future[T]]) =
    Future.sequence(lift(futures)) // having neutralized exception completions through the lifting, .sequence can now be used

  waitAll(SeqOfFutures).map { 
    // do whatever with the completed futures
  }

这篇关于Scala等待期货序列的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆