嗨,我正在研究 Scala Future ,并且在 Future / Promises 中扭曲了获取内部数据的方法。所以我写了所有我知道的模型,以获取Scala Futures的内部数据。
我们总是看到这两个案例:
1-有时我们会在异步函数块中获取 future internal data ,例如map,flatMap,foreach,fold,...
2-有时我们会在未来中获得结果,例如使用 Await
在此示例中,我使用Akka
?
或ask
函数(它是异步),我尝试了解如何获得结果的最佳做法未来
1- out of block?
2 in to block?
Await
,Sleep
,...)是不好的。请帮助我找到最佳做法替换Await
或Future.value.get.get
Tnx !!!
这是我的代码示例:
//Main Problem
val futureResult: Future[String] = (ping ? AskingTest).mapTo[String]
//Solution number 1
val awaitResult = Await.result(futureResult, myTimeout)
println(s"(1): $awaitResult")
//Solution number 2
val eitherResult: Either[Throwable, String] = Await.ready(futureResult, myTimeout).value.get match {
case Success(str) => println(s"(2): $str");Right(str)
case Failure(err) => println(s"(2): $err");Left(err)
}
//Solution number 3 ***low speed***
import scala.concurrent.ExecutionContext.Implicits.global
//BadPractice: Writ in play documentation.
futureResult map { x: String =>
println(s"(3): $x")
}
//Solution number 4
futureResult.value.get match {
case Success(str) => println(s"(4): $str")
case Failure(err) => println(s"(4)$err")
}
//Solution number 5
futureResult onComplete {
case Success(str) => println(s"(5): $str")
case Failure(err) => println(s"(5): $err")
}
答案 0 :(得分:3)
最佳做法是在世界尽头做一次等待""。这意味着您应该在一个未来组合所有未来,然后只等待一次。
val f1 = (ping1 ? AskingTest).mapTo[String]
val f2 = (ping2 ? AskingTest).mapTo[String]
val combinedFuture: Future[(String, String)] = for {
str1 <- f1
str2 <- f2
} yield (str1, str2)
// final await at the end of program
val (str1, str2) = Await.result(combinedFuture, Duration.Inf)
当我开始使用Futures编写代码时,我曾经在每行编写Await。这是错误的,因为它违背了使用期货的目的。
所以你的目标是使用for
组合尽可能多的未来,然后只等待一次。
除了No 4之外,上面列出的其他解决方案也没问题,因为如果未来尚未完成,可能会导致程序崩溃。
答案 1 :(得分:0)
正如您所提到的,阻止很糟糕,您只应在测试中使用它。
这是一个很好的博客,描述了可能性:testing-future-objects-scalatest
在现实生活中,你应该使用例如:
futureResult.foreach { x: String =>
// do some side effect
}
您必须确保调用此Future的进程未停止(例如在测试中)
另一个解决方案是使用Async - Await构造,它在Scala中有一个实现:scala-async