代码之家  ›  专栏  ›  技术社区  ›  user79074

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

  •  1
  • user79074  · 技术社区  · 6 年前

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

    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时的输出意味着它只接收将来从中发送的message3.foreach,而不是actor2返回的message3,因为这是由ask模式处理的。

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

    2 回复  |  直到 6 年前
        1
  •  3
  •   emilianogc    6 年前

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

    ask的主要目的是创建一个虚拟的actorRef,它使用的资源不如一个完全成熟的actorRef使用的资源那么多,可以作为一个可以回复的发送者。

    它只包装一个在接收到消息并且将来从ask函数返回时完成的承诺。

    因此,虽然从技术上讲您是从actor1请求的,但actor2中的sender()将是ask创建的虚拟promiseactor,这就是为什么您没有从actor2接收到message2的原因。

        2
  •  2
  •   Jeffrey Chung    6 年前

    ask ( ? )创建内部参与者以处理答复。一般来说,使用 tell ( ! )而不是 对于参与者之间的交流:

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