从斯卡拉期货获得价值

时间:2020-09-15 17:36:36

标签: scala

我是scala的新手,正在从事期货业务。因此,我有一个方法调用返回了Future,我的代码如下。

val futureResult =  data.getState  //this returns future
    Await.result(id, 10 seconds)  //  waiting for future to complete
  futureResult .onComplete({
      case Success(result) => logger.info(s"resultis.. ${result}")
      case Failure(exception) => exception.printStackTrace()
    })

万一成功,我会在“结果”中获得理想的结果。但是我想在一个变量中获取结果的值,以将其传递给其他方法。我尝试了。

val finalResult = futureResult.onComplete({
      case Success(result) => logger.info(s"resultis.. ${result}")
      case Failure(exception) => exception.printStackTrace()
    })

当我打印finalResult时,它为空。我该如何做才能具有结果价值,以便可以在其他地方使用

2 个答案:

答案 0 :(得分:1)

当您开始使用Futures和类似对象(根据其功能,统称为“ functors”或“ monads”)时,{check out this guide on functors with amazing animated pictures)会使用容器,具有特殊属性的盒子以及除非绝对必要,否则您不想从中“获得价值”。对于Future,容器表示异步计算的值。

这意味着您应该使用mapflatMap和类似方法来使用计算结果。这样,您可以使整个计算保持异步。同样,代码中的其他函数应返回Future并应尽可能地携带它们。 Here is the Scala docs overview on Future

同时,如果您将Future分配给变量,则是将“未来容器”分配给变量,而不是Future将包含的值。这就是为什么在第二个示例中无法打印finalResult的原因。

例如,您可以尝试:

def doSomething(value: String): Unit = ???
def calculateSomething(value: String): Boolean = ???
def calculateSomethingElse(value: Boolean): Future[Int] = ???

def myCode(...): Future[Int] = {
  someCallThatReturnsFutureOfString(...)
    .map { result =>
      logger.info(s"Result is... $result")
      // More computations with result
      doSomething(result)
      calculateSomething(result)
    }
    .flatMap { someCalculationResult =>
      // More computations....
      calculateSomethingElse(result)
    }
  }

如果要按照我的意愿处理异常,this other answer是您要寻找的东西,因为transform允许您操纵成功的结果以及异常。 / p>

futureResult transform {
  case Success(result) =>
    println(s"Result is... $result")
    // More computations with result
    Success(calculateSomething(result))

  case f @ Failure(exception) =>
    exception.printStackTrace()
    f
}

我知道,我好像没有回答你的问题。您可能会想“嘿,我想把价值发挥出来,并在其他地方使用它,这个家伙不是在告诉我”,但是除非有特殊的情况,否则这些价值将不被使用。转换为这种思维方式需要付出努力,一开始“看待如何完成”并不容易。

如果您仍然想获得价值,那么文森特的答案就是一个很好的答案。

答案 1 :(得分:0)

最好是这样:

val futureResult =  data.getState.map(res => fn(res))  //this returns future
  futureResult .onComplete({
      case Success(result) => logger.info(s"resultis.. ${result}")
      case Failure(exception) => exception.printStackTrace()
    })

或至少:

val futureResult =  data.getState  //this returns future
  futureResult .onComplete({
      case Success(result) => 
           logger.info(s"resultis.. ${result}")
           fn(result)
      case Failure(exception) => exception.printStackTrace()
    })

但是,执行Await.result会使您发现,如果Future失败,可能会引发异常,并使程序崩溃。

您期望的“ finalResult”包含的是Await.result返回的内容

请参见方法合同:

def result[T](awaitable : scala.concurrent.Awaitable[T], atMost : scala.concurrent.duration.Duration) : T