9

一个人会Future[Option[X]]变成Option[Future[X]]怎样?

val futOpt:Future[Option[Int]] = future(Some(1))
val optFut:Option[Future[Int]] = ?

更新:

这是对这个问题的跟进。我想我正试图掌握优雅地转换嵌套期货。我正在尝试用Options 来实现可以用Sequences 完成的事情,你可以先将 aFuture[Seq[Future[Seq[X]]]]变成双层Future[Future[Seq[Seq[x]]]],然后再变成flatMap双层。正如 Ionut 所澄清的那样,我已经以颠倒的顺序表达了这个问题,它应该是Option[Future[X]]-> Future[Option[X]]

4

2 回答 2

31

不幸的是,如果不丢失计算的非阻塞属性,这是不可能的。如果您考虑一下,这很简单。你不知道计算的结果是完成None还是Some直到Future完成,所以你必须这样Await做。到那时,再拥有一个已经没有意义Future了。您可以简单地返回Option[X],因为Future已经完成。

看看这里。它总是返回Future.successful,它不进行计算,只是无缘无故地包装o在 a中。Future

def transform[A](f: Future[Option[A]]): Option[Future[A]] =
  Await.result(f, 2.seconds).map(o => Future.successful(o))

所以,如果在你的上下文中阻止是有意义的,你最好使用这个:

def transform[A](f: Future[Option[A]]): Option[A] =
  Await.result(f, 2.seconds)

评论回复:

def transform[A](o: Option[Future[A]]): Future[Option[A]] =
  o.map(f => f.map(Option(_))).getOrElse(Future.successful(None))
于 2013-10-18T13:03:02.160 回答
0

从技术上讲,你可以做到这一点——在下面的片段中,我使用A绑定到一个幺半群的上下文,所以我的类型保持不变。


  def fut2Opt[A: Monoid](futOpt: Future[Option[A]])(implicit ec: ExecutionContext): Option[Future[A]] =
    Try(futOpt.flatMap {
      case Some(a) => Future.successful(a)
      case None    => Future.fromTry(Try(Monoid[A].empty))
    }).toOption

于 2021-01-31T18:35:36.477 回答