获取Scala Future的内部数据** BEST CASE **

时间:2018-04-19 12:04:31

标签: scala async-await future

,我正在研究 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?

  • 我们知道在异步时阻塞是不好的做法(因此使用AwaitSleep,...)是不好的。

请帮助我找到最佳做法替换AwaitFuture.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")
  }

2 个答案:

答案 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