在没有未来的情况下获得Scala承诺的结果

Getting the result of a Scala promise without a future

有没有办法直接从成功的承诺中获得价值?
为此,真的有必要将future连接到Promise吗?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
scala> import scala.concurrent._
import scala.concurrent._

scala> val result = Promise[Int]
result: scala.concurrent.Promise[Int] = scala.concurrent.impl.Promise$DefaultPromise@2b5fa85f

scala> result success 3
res0: result.type = scala.concurrent.impl.Promise$DefaultPromise@2b5fa85f

scala> result
res1: scala.concurrent.Promise[Int] = scala.concurrent.impl.Promise$DefaultPromise@2b5fa85f

scala> result.isCompleted
res4: Boolean = true

scala> result.value
<console>:12: error: value value is not a member of scala.concurrent.Promise[Int]
              result.value
                     ^

scala> result.future.value.get.get
res6: Int = 3

我正在考虑将诺言用于线程安全的"一次分配"语义。 在scala.concurrent源中,promise对象看起来足够精简,据我所知,它是线程安全的。 但是,我宁愿避免添加另一个对象(将来)。 对于诺言的成功价值,我找不到满意的答案。


tl;博士

1
p.future == p

所以不用担心额外的分配。

讨论区

PromiseFuture是互补的。前者代表计算的写入(一次),而后者代表读取。

因此,为了从Promise读取值,您将始终需要通过Future进行操作。

另一方面,值得注意的是,尽管进行了抽象设计,但实现还是非常有效的,并且PromiseFuture不是独立的实体。这是PromiseFuture的实现

1
2
3
private[concurrent] trait Promise[T] extends scala.concurrent.Promise[T] with scala.concurrent.Future[T] {
  def future: this.type = this
}

因此,您可以看到p.future实际上与p相同,并且只是获得了不同的语义。

最重要的是,您可以从promise访问Future,并且无需为实例分配支付任何额外费用。

另外,如果您愿意,可以使语法更好

1
2
3
4
5
6
7
8
9
10
scala> implicit class DirectAccessPromise[A](val p: Promise[A]) extends AnyVal {
     |   def get = p.future.value.get.get
     | }
defined class DirectAccessPromise

scala> val p = Promise.successful(42)
res0: scala.concurrent.Promise[Int] = scala.concurrent.impl.Promise$KeptPromise@5e8c92f4

scala> p.get
res1: Int = 42

请注意,由于包装器是值类,因此您无需支付任何额外的实例化价格


DefaultPromise将自己作为将来返回,因此您无需进行额外的分配。即使您是,线程安全性的代价也可能更高。