迷失Scala期货

时间:2016-08-10 21:51:46

标签: scala akka

我慢慢地将我的大脑缠绕在斯卡拉的Futures周围,并且有一层蛋糕正在进行中,我试图解开。

特定用例是sangria-graphql + akka中的DeferredResolver。我偷了他们的演示代码,看起来像这样

  Future.fromTry(Try(
    friendIds map (id => CharacterRepo.humans.find(_.id == id) orElse CharacterRepo.droids.find(_.id == id))))

并添加了我自己的修改。他们在内存中查找,而我的另一个人则问:

  Future.fromTry(Try(
    accountIds match {
      case h :: _ =>
        val f = sender ? TargetedMessage(h)
        val resp = Await.result(f, timeout.duration).asInstanceOf[TargetedMessage]
        marshallAccount(resp.body)

      case _ => throw new Exception("Not found")
    }
  ))

这里的相关部分是我选择列表中的第一个元素,将其发送到我在其他地方的ActorRef并等待结果。这有效。但是,我想要做的不是等待结果,而是将整个事情作为Future

返回
  Future.fromTry(Try(
    accountIds match {
      case h :: _ =>
        sender ? TargetedMessage(h) map {
          case resp:TargetedMessage => marshallAccount(resp.body)
        }

      case _ => throw new Exception("Not found")
    }
  ))

这不起作用。当这被消费时,而不是类型Account(函数marshallAccount的返回类型),它的类型为Promise。如果我理解正确,那是因为而不是返回类型为Future[Account],其类型为Future[Future[Account]]

我如何压扁这个?

1 个答案:

答案 0 :(得分:3)

您正在查看错误的API方法。 Future.fromTry用于创建一个立即解析的Future,这意味着该调用实际上并不是异步的。深入了解Future.fromTry的实现,它将带您进入:

def fromTry[T](result: Try[T]): Promise[T] = new impl.Promise.KeptPromise[T](result)

保留的承诺基本上是已经发生的事情,所以就像Future.successful这只是用来确保正确的返回类型或类似,它实际上并不是制作异步的方法。

返回类型为Future[Future[Something]]的原因是因为您试图将已经返回未来的东西包装到另一个未来。

问询模式,即sender ? TargetMessage(h)是一种询问某个演员的方式并等待结果的方式,这将返回未来。

正确的方法:

val future: Future[Account] = accountIds match {
  case h :: _ => sender ? TargetedMessage(h) map (marshallAccount(_.body)
  case _ => Future.failed(throw new Exception("Not found"))
}

基本上,如果要保持返回类型一致,则需要使用Future.failed从异常中返回失败的未来。值得回顾this tutorial以了解更多有关期货以及如何使用它们编写应用程序逻辑的信息。