检查已完成 Promise 值的正确方法?

Ash*_*ynd 2 concurrency scala promise

上下文:我有一个函数,我想在开始时检查某个 Promise 是否 a) 已经完成并且 b) 具有某个值。

Scala 中有一个方法可以检查 Promise 是否已经完成(从 2.11.5 开始),即isCompleted. 然而,当你想要获得已经完成的 Promise 的值时,看起来你必须像这样写一个令人讨厌的链:

val p = Promise[Boolean]
val result = p.future.value.get.toOption.get
Run Code Online (Sandbox Code Playgroud)

(为了完整性:我正在考虑写一些类似的东西:

if (p.isCompleted && p.future.value.get.toOption.get == true)
Run Code Online (Sandbox Code Playgroud)

但对代码的丑陋感到震惊:))

没有更好的办法吗?或者这是否表明我没有按照预期的方式使用它?

JLR*_*she 5

我会说你没有按照预期的方式使用它。

首先,Scala Promises 主要是一种“引导” Futures 的机制,因此您传递的值通常应该是 Futures 而不是 Promises。这使得访问链缩短了一段。

接下来,你要经历这么多层的原因是 Futures 封装了两种效果——并发和失败。Future 可以完成也可以失败,所以检查isCompleted只是故事的一半。

所以你在这里可以做的是使用模式匹配。Some/None 模式匹配检查已完成/未完成,因此您无需对.isCompleted属性进行显式检查。在这里,我假设你有一个 Futuref而不是 Promise,但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
}
Run Code Online (Sandbox Code Playgroud)

在您的具体情况下,这将归结为 Sarvesh 在他的回答中所展示的内容,尽管我认为您很有可能实际上应该处理错误不是完整的案例,而不仅仅是将它们视为false.

使用 Futures 的另一种方法是以事件驱动的方式使用它们。您可以注册的事件f.andThenf.onFailuref.onSuccess取决于哪些结果要注意观察,你可以用用各种其他机制改变他们的结果等。