【问题标题】:Why Scala Future returns None using flatMap and for comprehension?为什么 Scala Future 使用 flatMap 和理解返回 None?
【发布时间】:2014-04-20 06:12:44
【问题描述】:

我有以下 Scala 代码,用于 Scala 2.10

package reactive

import scala.concurrent.future
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.Future

object futuresum extends App {

  def f1 = future { 12 }
  def f2 = future { 13 }

  val result1 = f1.flatMap(x => f2.map(y => x + y))
  println(result1.value)

  val result2 = for (x <- f1; y <- f2) yield (x + y)
  println(result2.value)

}

这段代码应该打印25,但它打印None

None
None

这段代码有什么问题?

编辑

这对我有用:

package reactive

import scala.concurrent.future
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.Future
import scala.concurrent.Await
import scala.concurrent.duration.Duration

object futuresum extends App {

  def f1 = future { 12 }
  def f2 = future { 13 }

  val result1 = f1.flatMap(x => f2.map(y => x + y))
  result1.onComplete(b => println(b))

  val result2 = for (x <- f1; y <- f2) yield (x + y)
  result2.onComplete(b => println(b))

  Await.result(result1, Duration.Inf)
  Await.result(result2, Duration.Inf)
}

【问题讨论】:

    标签: scala future reactive-programming


    【解决方案1】:

    我的猜测是,在“结果”和它的 println 之间,期货没有足够的时间来生成/发送到他们的线程。检查这个快速的 REPL 会话:

    scala> f1.flatMap(x => f2.map(y => x + y)).value
    res2: Option[scala.util.Try[Int]] = None
    
    scala> f1.flatMap(x => f2.map(y => x + y))
    res3: scala.concurrent.Future[Int] = scala.concurrent.impl.Promise$DefaultPromise@1c9dac55
    
    scala> res3.value
    res4: Option[scala.util.Try[Int]] = Some(Success(25))
    

    让我们尝试一些不同的东西:

    scala> f1.flatMap(x => f2.map(y => x + y)).onComplete(println(_))
    
    scala> Success(25) // Press enter here. onComplete mixed with REPL output.
    

    再试一次:

    scala> val later=f1.flatMap(x => f2.map(y => x + y)); later.onComplete(println(_)); println(later.value);
    None
    later: scala.concurrent.Future[Int] = scala.concurrent.impl.Promise$DefaultPromise@7019b737
    Success(25)
    

    现在这是一个令人困惑的输出。不过,这很好地说明了我的观点:

    1. 首先,创建later,其中包含一个计算 在未来的某个时间执行。
    2. 将此计算与将在完成时触发的事件绑定。
    3. 打印可能未完成的计算结果。

    现在考虑两行执行。 1、2 和 3 发生在第一条执行主线或主线程中。未来的事情,{ 12 }mapflatMat 发生在另一行执行中。

    【讨论】:

      【解决方案2】:

      我会从https://stackoverflow.com/a/16358119/3328933 那里窃取 Régis Jean-Gilles 的出色回答

      "Futures在专用线程池上执行。如果你的主程序不等待future,它会立即退出,future没有机会执行。你可以在这里做的是使用Await在你的主程序阻塞主线程直到未来执行:"

      package reactive
      
      import scala.concurrent.Await
      import scala.concurrent.ExecutionContext.Implicits.global
      import scala.concurrent.future
      import scala.concurrent.duration._
      
      object futuresum extends App {
      
          def f1 = future { 12 }
          def f2 = future { 13 }
      
          val result1 = f1.flatMap(x => f2.map(y => x + y))
          result1 onSuccess { case res => println(res) }
          Await.result(result1, 2 seconds)
      
          val result2 = for (x <- f1; y <- f2) yield (x + y)
          result2 onSuccess { case res => println(res) }
          Await.result(result2, 2 seconds)
      }
      

      【讨论】:

        【解决方案3】:

        使用 Await.result(result, duration) 或 Thread.sleep 等待未来线程完成。 然后您可以检查future.isComplete 以确保future 已完成。

         Await.result(result2, 3 seconds)
         if(result2.isCompleted)
         println(result2.value)
        

        【讨论】:

          猜你喜欢
          • 2014-10-14
          • 2013-08-14
          • 2015-01-05
          • 2014-02-23
          • 1970-01-01
          • 2021-11-25
          • 1970-01-01
          • 2016-10-04
          相关资源
          最近更新 更多