组成必需和可选值的期货

Composing Futures of a required and optional value

假设我正在编写一个接收 Future[A]Future[B] 以及 returns Future[(A, Option[B])] 的函数,如下所示:

// return the result of "fa" and then
// either "Some" of the result of "fb" if "fb" has been completed successfully
// or None if "fb" is still not completed or failed
// Note: we check `fb` result after `fa` has completed.

def foo(fa: Future[A], fb: Future[B]): Future[(A, Option[B])] = ???

// foo(Future.successful(a), Future.successful(b)) // Future.successful(a, Some(b))
// foo(Future.successful(a), Future.failed(...))   // Future.successful(a, None)
// foo(Future.successful(a), Future.never)         // Future.successful(a, None)
// foo(Future.failed(...),   Future.successful(b)) // Future.failed(...)
// foo(Future.failed(...),   Future.never)         // Future.failed(...)

我这样写foo

def foo(fa: Future[A], fb: Future[B]): Future[(A, Option[B])] = for {
  a <- fa
  ob <- if (fb.isCompleted) fb.recover { case NonFatal(_) => None } else Future.successful(None)
} yield (a, ob)

这个实现似乎有效。你会如何纠正或改进它?

您可以使用 value

轻松定义 foo
def foo(fa: Future[A], fb: Future[B])(implicit ec: ExecutionContext): Future[(A, Option[B])] =
  fa.map(a => a -> fb.value.flatMap(_.toOption))

这非常有效,因为 value 完全代表您想要的,即 Future 的值(如果它完成)或 None;此外,由于该值还捕获了作为 Try 失败的可能性,而您想要的只是将其转换为 Option ,您有一个漂亮的 -班轮.

一如既往,Scaladoc 是你的朋友 ;)