我有一个提供Context的函数:
def buildContext(s:String)(request:RequestHeader):Future[Granite.Context] = {
    .... // returns a Future[Granite.Context]
}
然后我有另一个函数,它使用Context来返回一个Option [Library.Document]:
def getDocument(tag: String):Option[Library.Document] = {
   val fakeRequest = play.api.test.FakeRequest().withHeaders(CONTENT_TYPE -> "application/json")
   val context = buildContext(tag)(fakeRequest)
   val maybeDoc = context.getDocument //getDocument is defined on Granite.Context to return an Option[Library.Document]
}
如果Future已经返回,这段代码将如何考虑?我已经看到/ yield曾经等待返回,但我总是认为for/yield只是将事情拼凑在一起并且与等待Futures返回没有任何关系.我有点卡在这里,并不是真的没有正确的问题要问!
fla*_*ian 10
另外两个答案是误导性的.for yieldScala中的A 是一个转换为map或flatMap链的编译器原语.Await如果可以避免使用,请不要使用,这不是一个简单的问题.
您正在介绍阻止行为,并且您尚未意识到阻止时所做的系统性损害.
当涉及到Future,map并flatMap做不同的事情:
将 在未来完成时执行map.这是一种进行类型安全映射的异步方法.
val f: Future[A] = someFutureProducer
def convertAToB(a: A): B = {..}
f map { a => convertAToB(a) } 
flatMap
是你用来链接东西的东西:
someFuture flatMap {
  _ => {
    someOtherFuture
  }
}
相当于上述内容:
for {
  result1 <- someFuture
  result2 <- someOtherFuture
} yield result2
在Play中你会Async用来处理上面的事情:
Async {
    someFuture.map(i => Ok("Got result: " + i))
}
更新
我误解了你对Play的使用.不过,它并没有改变任何东西.您仍然可以使您的逻辑异步.
someFuture onComplete {
  case Success(result) => // doSomething
  case Failure(err) => // log the error etc
}
在异步思考时的主要区别在于,您始终必须map并且flatMap在Futures中执行其他所有操作才能完成任务.性能提升很大.
你的应用越大,收益越大.
当Future你在a上使用for-comprehension时,你不是在等待它完成,你只是说:当它完成时,像这样使用它,For-comprehension Future在这种情况下返回另一个.
如果您想等待将来完成,您应该使用Await如下:
val resultContext = Await.result(context , timeout.duration)
然后对它运行getDocument方法:
val maybeDoc = resultContext.getDocument
编辑
然而,与期货合作的常用方法是等到你之前的最后一刻Await.正如另一个答案所指出的,Play Framework通过允许您返回来做同样的事情Future[Result].所以,一个好的方法就是只使用for-comprehensions并让你的方法返回Futures等,直到你想要最终返回结果的最后一刻.
| 归档时间: | 
 | 
| 查看次数: | 7097 次 | 
| 最近记录: |