我的代码:为什么通过理解展开未来的结果类型是未来?
val f1 = Future[String] { "ok1" }
val fRes: Future[String] = for { r <- f1 } yield r
我希望fRes
是一个字符串,但我得到一个Future[String]
。为什么?我不想使用Await.result
。
我的代码:为什么通过理解展开未来的结果类型是未来?
val f1 = Future[String] { "ok1" }
val fRes: Future[String] = for { r <- f1 } yield r
我希望fRes
是一个字符串,但我得到一个Future[String]
。为什么?我不想使用Await.result
。
看看onComplete
。你可以拨打电话,像这样:
import scala.util.{Success, Failure}
val f1: Future[String] = Future {"ok1"}
var myString = ""
f onComplete {
case Success(s) => myString = s
case Failure(t) => println("An error has occured: " + t.getMessage)
}
如果您在'f1'完成之前使用'myString',它仍然是空的。如果你真的想从'Future'中获得'String',最好阻止使用'Await.result'。更好的方法是留在'Future'上下文中并使用'flatMap'和'map'。 –
请不要暗示这样的举动,因为这是一种直接进入竞赛状态的方式。将回调中的可变状态关闭到'Future's是非常危险的 - 它们在不同的线程上执行,即使回调已经完成并成功地改变了'var',其他线程也可能在没有额外的同步努力的情况下看到它的数据。因此,您的程序可能会通过所有测试并在大多数时间按预期工作,并且有时可能会意外中断。有关并发危害的更多信息,请参阅Brian Goetz的“Java Concurrency in Practice”。 – Sergey
我知道,当然@Sergey。 OP特别要求一种不用“await”的方法来做到这一点,这就是为什么会这样做的原因。 –
的for
和yield
组合不“解包”的Future
。 在实践中,这是一件好事。
所以每样Option
,Try
,List
或任人功能人们称它为Applicative Functor
保持它的类型这种方式。
由于这个属性,你可以编写内的for { <- }
如同代码是“展开”,但仅仅是因为它是由确保代码以外的东西撑包裹。
当你看到for-comprehension
做什么时,它可能会更清晰。它是链式map
和flatMap
操作的语法糖。
val x: Option[_] = Some(5).map{ i =>
// i is "unwrapped" here
(i * i).toString
}
val x: Option[_] = for {
i <- Some(5)
} yield i.toString // i unwrapped for the for comprehension but will keep Option type
如果你想在结束访问的未来价值和做与它synchronuous程序流的东西,你只需要选择
由于@Robert Udah建议你可以使用onComplete
并有回调功能或者您必须使用Await
。
看看这里如何使用期货:http://docs.scala-lang.org/overviews/core/futures.html –
理解内的'r'是一个'String',但'你得到的是一个'Future [String]'。阅读@RobertUdah链接的页面以获得“未来”的感觉是个不错的主意。对于'flatMap'' +'map'来说,理解只是一种明智的语法。在你的情况中,对于{r < - f1},yield r'与'f.map(r - > r)'是一样的,所以你最终用同样的'Future [String]'结束。 –
你不会得到一个字符串,因为理解不会阻止等待未来完成。 – nedim