询问模式覆盖消息是否收到

时间:2019-01-15 11:34:41

标签: scala akka

我定义了以下消息和参与者:

case class Message1(text: String)
case class Message2(text: String)
case class Message3(text: String)

class Actor1(actor2: ActorRef) extends Actor {
    def receive = {
        case Message1(text) =>
            (actor2 ? Message2(text)).mapTo[Message3].foreach(self ! _)
        case Message3(text) =>
            println(s"Got the message[$sender]: " + text)
    }
}

class Actor2 extends Actor {
    def receive = {
        case Message2(text) =>
            println(s"Actor2[$self] received: " + text)
            sender ! Message3("Received message1: " + text)
    }
}

def main(args: Array[String]): Unit = {

    val system = ActorSystem("Test")
    system.actorOf(Props(new Actor1(system.actorOf(Props(new Actor2))))) ! Message1("Hello")
}

当我运行此代码时,Actor1收到Message3时的输出暗示它仅接收从Future.foreach内部发送的Message3,而不是Actor2发送回的消息3-因为这是由Ask模式处理的。

所以我的问题是:这始终是预期的行为吗?

2 个答案:

答案 0 :(得分:3)

是的,这实际上是预期的行为。

ask的主要目的是创建一个虚拟ActorRef,该虚拟ActorRef的使用资源不如一个全副武装的actor充当您可以回复的发件人。

它只包装一个诺言,当收到消息并从Ask函数返回前途时,诺言就会完成。

因此,尽管从技术上讲您是从Actor1询问的,但Actor2中的sender()将是询问创建的伪PromiseActor,这就是为什么您不从Actor2接收Message2的原因。

答案 1 :(得分:2)

ask?)创建一个内部参与者来处理回复。通常,使用tell!)代替ask进行角色间通信:

class Actor1(actor2: ActorRef) extends Actor {
  def receive = {
    case Message1(text) =>
      actor2 ! Message2(text)
    case Message3(text) =>
      println(s"Got the message[$sender]: $text")
  }
}