为什么我们需要未来和承诺?

时间:2016-10-30 17:26:52

标签: scala jvm promise future

据我所知,Future是只读的,Promise是一次写入数据结构。

我们需要Promise来完成Future

例如,

object Lie extends Throwable

val lie = Future { throw Lie } 

val guess = Promise[String]()     

lie.onComplete { case Success(s) => guess.success("I knew it was true!") 
                 case Failure(t) => guess.failure("I knew it was lie")} 
// return type: Unit 

guess.future.map(println) 
// res12: scala.concurrent.Future[Unit] = List()
// I knew it was lie!
// Requires Promise to chain Future with exception 


但是,我无法理解为什么我们需要同时拥有FuturePromise

由于Promise签名

,我认为Future.onComplete是必需的

由于Future.onComplete返回类型为UnitFuture可能无法链接

我认为Promise是为了克服这种限制而引入的


但为什么不改变Future.onComplete的签名呢?

Future.onComplete的返回类型更改为Future[T]将启用Future上的链接,但异常

然后,Future不需要Promise

例如,上面的代码可以更改为

val lie = Future { throw Lie } 

lie.onComplete { 
   case Success(s) => "I knew it was true!"
   case Failure(t) => "I knew it was lie!"
}.map(println) 

//onComplete return type is Future[String]


我的问题是

1)我是对的吗? Future不需要Promise,如果onComplete签名从Unit更改为Future[T]

2)为什么将未来和承诺分开?

UDPATE

感谢回复者,现在我理解了Promise的目的。 Future链接

实际上并非如此

如果可以的话,我可以问你吗

为什么onComplete会返回Unit ??

它实际上可以返回Future[T]以便轻松启用链接

例如

Future { throw Error }.onComplete {
  case Success(s) => "Success" 
  case Failure(t) => throw Error
}.onComplete {
  case Success(s) => "Success"
  case Failure(t) => throw Error 
}. ... 

3 个答案:

答案 0 :(得分:6)

Future.apply[T](block: => T): Future[T]Future.unit.map(_ => block) [1]

的语法糖

Future表示,可能当前 可用。

Promise表示有义务在某个时间提供

Future(用于读取)和Promise(用于写入)具有单独的实体意味着很容易推断出功能:

  • 当Future是一个参数时,它是一个请求在某个时候有一些值,当它被用作一个返回类型时,它的响应可能不是目前可用。

  • 当Promise是一个参数时,它就是"消费"在某些时候产生某些价值的责任,当它被用作回报类型时,它就是生产和#34;在某些时候产生价值的责任。

总而言之,能够推断功能,特别是在异步,甚至并发程序中,是非常有价值的。

大多数时候Promise不需要使用,因为它由Future-combinators透明地处理 - 但是当与第三方软件或网络库集成时,它可能非常有用。

有关Scala 2.12中有趣的新功能的更多信息,请查看here

1:Future.unit 定义为: val unit: Future[Unit] = Future.successful(())

答案 1 :(得分:2)

  我是对的吗?如果Future签名是Promise,那么onComplete不需要Future[T]   从单位改为未来[T]?

你把事情搞混了。让我们澄清一下。

Future.apply表示将在未来完成的计算。也就是说,您传递ExecutionContext一个函数,该函数将在您定义的某些Promise[T]指定的线程上执行。

现在,另一方面,Future[T]是一种创建Future[T] 的方式,而无需实际创建Future.successful。一个很好的例子是Promise.successful方法(内部消耗def successful[T](result: T): Future[T] = Promise.successful(result).future ):

ExecutionContext

如果有任何其他资源,则不需要Future[T],也不需要排队。它只是一个方便的包装器,允许您“人工”创建TestCase

答案 2 :(得分:1)

没有

Future无法涵盖Promise的用例。 Promise有自己的价值。您无法将Future替换为Promise

Future表示稍后可用的计算。未来执行完成后,您可以使用onComplete获得结果,并且可以使用mapflatMaprecoverrecoverWith撰写期货。

  

Promise是一次性写入容器,客户端可以订阅容器。当订阅客户端获得未来等待,直到将值写入名为promise的容器中。

未来是只读的

  

您不能将future用作一次性写入容器。你只能从将来读。

但是Promise是不同的。

  

如果您想为用户提供一些您现在没有的东西,但您认为很快就能拥有它,该怎么办?

这意味着您承诺用户现在没有的东西。

因此,您希望让用户等待,直到您拥有将其提供给用户的内容。那就是当你p.future并生成一个未来,以便用户可以等待未来的结果。

如果您获得了承诺给用户的结果,那么当发生不良事件时(即通过执行success),您可以将未来设为failurep.complete,从而为用户提供帮助

  

即使onComplete返回类型更改为Future[T]Future Promise无法表达或服务于Future.apply

使用Future随播对象创建未来

也可以使用byte[] ref = {0x71, 0, 0x7e, 0, 5}; // Ref #5 创建未来。在这种情况下,一旦未来的计算完成,未来创建的将完成。

  

Future用于订阅耗时计算的结果,而Promise可以是发布和订阅模型。