3

我正在使用 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 也不会“返回”任何内容,因此超时总是会过期。我究竟做错了什么?非常感谢。

4

1 回答 1

3

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

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

警告

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

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

def receive = {
  case Calculate(tonumber: Int) =>
    ...
    sender ! 12345
  case _ =>
    sender ! akka.actor.Status.Failure(new InvalidArgumentException)
}
于 2013-02-08T12:58:31.073 回答