2016-06-07 38 views
1

我的代码:为什么通过理解展开未来的结果类型是未来?

val f1 = Future[String] { "ok1" } 
val fRes: Future[String] = for { r <- f1 } yield r 

我希望fRes是一个字符串,但我得到一个Future[String]。为什么?我不想使用Await.result

+1

看看这里如何使用期货:http://docs.scala-lang.org/overviews/core/futures.html –

+0

理解内的'r'是一个'String',但'你得到的是一个'Future [String]'。阅读@RobertUdah链接的页面以获得“未来”的感觉是个不错的主意。对于'flatMap'' +'map'来说,理解只是一种明智的语法。在你的情况中,对于{r < - f1},yield r'与'f.map(r - > r)'是一样的,所以你最终用同样的'Future [String]'结束。 –

+0

你不会得到一个字符串,因为理解不会阻止等待未来完成。 – nedim

回答

-3

看看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) 
} 
+3

如果您在'f1'完成之前使用'myString',它仍然是空的。如果你真的想从'Future'中获得'String',最好阻止使用'Await.result'。更好的方法是留在'Future'上下文中并使用'flatMap'和'map'。 –

+0

请不要暗示这样的举动,因为这是一种直接进入竞赛状态的方式。将回调中的可变状态关闭到'Future's是非常危险的 - 它们在不同的线程上执行,即使回调已经完成并成功地改变了'var',其他线程也可能在没有额外的同步努力的情况下看到它的数据。因此,您的程序可能会通过所有测试并在大多数时间按预期工作,并且有时可能会意外中断。有关并发危害的更多信息,请参阅Brian Goetz的“Java Concurrency in Practice”。 – Sergey

+0

我知道,当然@Sergey。 OP特别要求一种不用“await”的方法来做到这一点,这就是为什么会这样做的原因。 –

1

foryield组合不“解包”的Future。 在实践中,这是一件好事。

所以每样OptionTryList或任人功能人们称它为Applicative Functor保持它的类型这种方式。

由于这个属性,你可以编写for { <- }如同代码是“展开”,但仅仅是因为它是由确保代码以外的东西撑包裹。

当你看到for-comprehension做什么时,它可能会更清晰。它是链式mapflatMap操作的语法糖。

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