上下文:我有一个函数,我想在开头检查某个Promise已经a)已经完成并且b)具有一定的值。
有一种方法可以检查Scala中的Promise(从2.11.5开始)是否已经完成,即isCompleted
。但是,当你想获得已经完成的Promise的值时,看起来你必须编写一个像这样的unappetising链:
val p = Promise[Boolean]
val result = p.future.value.get.toOption.get
(为了完整性:我正在考虑写一些类似的东西:
if (p.isCompleted && p.future.value.get.toOption.get == true)
但对该代码的丑陋感到震惊:))
有没有更好的方法?或者这是否表明我没有像预期的那样使用它?
答案 0 :(得分:4)
我会说你没有像预期的那样使用它。
首先,Scala Promises主要是一种“引导”期货的机制,因此您传递的价值通常应该是期货而非Promise。这使得访问链段缩短了一段。
接下来,你经历这么多层的原因是Futures封装了两个效果 - 并发和失败。未来可以完成并失败,因此检查isCompleted
只是故事的一半。
所以你可以在这里做的是使用模式匹配。 Some / None模式匹配检查已完成/未完成,因此您无需显式检查.isCompleted
属性。在这里,我假设你有一个未来f
而不是一个承诺,但如果你需要,你可以对p.future
做同样的事情:
f.value match {
case Some(Success(v)) => // completed successfully - access value v
case Some(Failure(e)) => // completed with failure - access error e
case None => // not yet complete
}
在你的具体案例中,这将归结为Sarvesh在他的回答中所表明的内容,尽管我说你很有可能实际上应该处理错误并且没有完成< / em>案例,而不仅仅是将它们视为false
。
使用Futures的另一种方法是以事件驱动的方式使用它们。您可以在f.andThen
,f.onFailure
,f.onSuccess
上注册事件,具体取决于您要观察的结果,并且您可以使用各种其他机制来转换其结果等。< / p>
答案 1 :(得分:2)
Future[T].value
会返回Option[Try[T]]
,如果未来尚未完成,则为无,因此您无需另行isCompleted
。这意味着您可以将方法编写为:
def hasValue[T](p: Promise[T], value: T) = p.future.value.flatMap(_.toOption) == Some(value)
答案 2 :(得分:-1)
所以......基本上,承诺是一种包装物,它允许我们与潜在的未来互动。
所以......从完成的承诺中获取你的未来并使用模式匹配。
在这种情况下,p.future.value将为Option[ Try [ Boolean ] ]
val yourBool = p.future.value match {
case Some( Success( bool ) ) => bool
case _ => false
}