Phoenix PubSub 事件多次触发

问题描述 投票:0回答:1
  def join("world:lobby", _message, socket) do
    PubSub.subscribe(Rotb.PubSub, "zone_1")

    {:ok, socket}
  end


  def handle_info(%{message: message}, socket) do
    broadcast(socket, "shout", %{"socket_id" => socket.id, "message" => message})

    {:noreply, socket}
  end

  def handle_in("shout", payload, socket) do
    PubSub.broadcast(Rotb.PubSub, "zone_1", %{
      message: payload["message"]
    })

    {:noreply, socket}
  end

但是喊叫事件在我的客户端上发生了多次?看起来彼此连接可能会出现额外的时间,但不是 100%。

elixir phoenix-framework phoenix-channels
1个回答
0
投票

如果我正确理解你在做什么,你希望所有连接到凤凰频道的客户端都能听到声音。

那里的 PubSub 订阅很有意义。

句柄信息中的广播没有意义,因为它是针对当前客户端的。你应该只是在那里推动。请参阅下面的代码以及连接了两个客户端的 React Native 控制台的屏幕截图。广播已处理

defmodule MyAppWeb.TestChannel do
  use Phoenix.Channel

  alias Phoenix.PubSub

  def join("world:lobby", _message, socket) do
    PubSub.subscribe(MyApp.PubSub, "zone_1")

    {:ok, socket}
  end

  def handle_info(%{message: message}, socket) do
    IO.inspect({"NEW MESSAGE", message})
    push(socket, "shout", %{"socket_id" => socket.id, "message" => message})

    {:noreply, socket}
  end

  def handle_in("shout", payload, socket) do
    IO.inspect({"SHOUT", payload})

    PubSub.broadcast(MyApp.PubSub, "zone_1", %{
      message: payload["message"]
    })

    {:noreply, socket}
  end
end

喊声是从 Android 客户端发出的。如果您连接了两个客户端,那么您应该会看到每个套接字有两个不同的 pid。

现在,如果您只是尝试将消息广播到所有连接的客户端,则应该只使用 handle_in 中的 broadcast/3,而不是使用 PubSub。 PubSub 用于从套接字外部推送消息。就像某些 cron 作业一样,它会发现其他外部状态是否已更改,然后将其推送到套接字。对于从一个客户端向其他客户端广播消息,那么 handle_in 内的 broadcast/3 就足够了

在handle_info中使用广播和pubsub意味着所有客户端都获得pubsub然后它们都广播。没有你想要的。

© www.soinside.com 2019 - 2024. All rights reserved.