组成必需值和可选值的期货
Posted
技术标签:
【中文标题】组成必需值和可选值的期货【英文标题】:Composing Futures of a required and optional value 【发布时间】:2021-07-26 21:30:02 【问题描述】:假设我正在编写一个接收Future[A]
和Future[B]
并返回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)
这个实现似乎有效。您将如何纠正或改进它?
【问题讨论】:
【参考方案1】:您可以使用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 是您的朋友 ;)
【讨论】:
值得注意的是,此解决方案需要在范围内隐式使用 ExecutionContext。我会考虑fa.zip(Future.successful(fb.value.flatMap(_.toOption)))
或者使用ExecutionContext.parasitic
明确传递给fa.map
,因为要做的工作很少而且没有影响。
@ViktorKlang 谢谢。 fb.value
是否在 fa
完成后调用?我需要等待fa
完成,然后检查fb
是否完成。我猜map
解决方案是这样工作的。
啊,所以你想要“最早在 fa 完成后”的值?然后 map 会更好,因为 zip 渴望在其参数中。
是的,我想要在完成fa
之后的value
。我将更新问题以使其清楚。以上是关于组成必需值和可选值的期货的主要内容,如果未能解决你的问题,请参考以下文章
Swift:XCTest 会修改状态吗?可以返回可选值的测试函数的约定是啥?