【问题标题】:Scala Akka Play, Future doesn't returnScala Akka Play,Future 不会返回
【发布时间】:2013-01-24 05:48:39
【问题描述】:

我正在使用 Scala 2.10、Akka 2.1 和 Play 2.1。当我向我的后端发送一个 http 请求时,我 ask 一个演员来计算一些东西。这个想法是如果它在超时之前返回,则返回计算结果,否则返回不同的字符串。请参阅下面的代码。

val futureInt: Future[Int] = ask(testActor, Calculate(number.toInt)).mapTo[Int]
val timeoutFuture = play.api.libs.concurrent.Promise.timeout("Oops", 2.seconds)

Async {
  Future.firstCompletedOf(Seq(futureInt, timeoutFuture)).map {
    case i: Int => Ok("Got result " + i)
    case t: String => Ok("timeout expired")
  }
}

演员如下:

class TestActor() extends Actor {
  def receive = {
    case Calculate(tonumber: Int) =>
      for (a <- 1 to tonumber) {
        val c: Double = scala.math.pow(a, 2)
        println("a: " + a + ", c: " + c)
      }
      12345 // hardcoded value to return when the calculation finishes
    case _ =>
      println("bah")
  }
}

我的问题是,即使演员在超时之前完成,Future 也不会“返回”任何内容,因此超时总是会过期。我究竟做错了什么?非常感谢。

【问题讨论】:

    标签: scala playframework akka future


    【解决方案1】:

    来自http://doc.akka.io/docs/akka/snapshot/scala/actors.html

    使用 ask 会像 tell 一样向接收 Actor 发送消息,接收 Actor 必须回复 sender !回复以用一个值完成返回的 Future。

    警告

    要完成带有异常的未来,您需要向发件人发送失败消息。当参与者在处理消息时抛出异常时,这不会自动完成。

    因此,不要像在通常的 scala 函数中那样“返回”,而是按照以下方式做一些事情

    def receive = {
      case Calculate(tonumber: Int) =>
        ...
        sender ! 12345
      case _ =>
        sender ! akka.actor.Status.Failure(new InvalidArgumentException)
    }
    

    【讨论】:

    • 嘿迪伦,感谢您的回复。但是,从 akka 文档中,您的建议仅在演员已被另一个演员调用时才有效:“通常有两种方法可以从演员那里获得回复:第一种是通过发送的消息(演员!msg),它只有效如果原始发件人是演员),第二个是通过未来。”
    • 没关系。您的解决方案是可行的。我要给akka团队发消息!
    • ask 模式在后台创建了必要的参与者,因此您的参与者确实将消息发送回另一个参与者。但是,作为调用者的您会按预期收到未来。
    猜你喜欢
    • 2018-05-25
    • 2017-08-02
    • 2018-04-17
    • 1970-01-01
    • 2021-07-14
    • 2023-03-06
    • 1970-01-01
    • 2018-12-18
    • 2016-08-01
    相关资源
    最近更新 更多