scala用于与Future一起使用的良率理解.如何等到未来回来?

Zur*_*iar 7 scala

我有一个提供Context的函数:

def buildContext(s:String)(request:RequestHeader):Future[Granite.Context] = {
    .... // returns a Future[Granite.Context]
}
Run Code Online (Sandbox Code Playgroud)

然后我有另一个函数,它使用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]

}
Run Code Online (Sandbox Code Playgroud)

如果Future已经返回,这段代码将如何考虑?我已经看到/ yield曾经等待返回,但我总是认为for/yield只是将事情拼凑在一起并且与等待Futures返回没有任何关系.我有点卡在这里,并不是真的没有正确的问题要问!

fla*_*ian 10

另外两个答案是误导性的.for yieldScala中的A 是一个转换为mapflatMap链的编译器原语.Await如果可以避免使用,请不要使用,这不是一个简单的问题.

您正在介绍阻止行为,并且您尚未意识到阻止时所做的系统性损害.

当涉及到Future,mapflatMap做不同的事情:

在未来完成时执行map.这是一种进行类型安全映射的异步方法.

val f: Future[A] = someFutureProducer
def convertAToB(a: A): B = {..}
f map { a => convertAToB(a) } 
Run Code Online (Sandbox Code Playgroud)

flatMap

是你用来链接东西的东西:

someFuture flatMap {
  _ => {
    someOtherFuture
  }
}
Run Code Online (Sandbox Code Playgroud)

相当于上述内容:

for {
  result1 <- someFuture
  result2 <- someOtherFuture
} yield result2
Run Code Online (Sandbox Code Playgroud)

在Play中你会Async用来处理上面的事情:

Async {
    someFuture.map(i => Ok("Got result: " + i))
}
Run Code Online (Sandbox Code Playgroud)

更新

我误解了你对Play的使用.不过,它并没有改变任何东西.您仍然可以使您的逻辑异步.

someFuture onComplete {
  case Success(result) => // doSomething
  case Failure(err) => // log the error etc
}
Run Code Online (Sandbox Code Playgroud)

在异步思考时的主要区别在于,您始终必须map并且flatMapFutures中执行其他所有操作才能完成任务.性能提升很大.

你的应用越大,收益越大.


Pet*_*ter 6

Future你在a上使用for-comprehension时,你不是在等待它完成,你只是说:当它完成时,像这样使用它,For-comprehension Future在这种情况下返回另一个.

如果您想等待将来完成,您应该使用Await如下:

val resultContext = Await.result(context , timeout.duration)
Run Code Online (Sandbox Code Playgroud)

然后对它运行getDocument方法:

val maybeDoc = resultContext.getDocument
Run Code Online (Sandbox Code Playgroud)

编辑

然而,与期货合作的常用方法是等到你之前的最后一刻Await.正如另一个答案所指出的,Play Framework通过允许您返回来做同样的事情Future[Result].所以,一个好的方法就是只使用for-comprehensions并让你的方法返回Futures等,直到你想要最终返回结果的最后一刻.