【问题标题】:Broadcast to different channel Phoenix 1.1.6广播到不同频道 Phoenix 1.1.6
【发布时间】:2016-11-27 20:05:39
【问题描述】:

我正在尝试向我的应用程序中的其他频道广播,但我无法让它工作。我也想写一个测试,但我不知道怎么做。

据我所知,我成功地从 notification_channel 广播了消息,但在 chat_channel 中没有收到。

通知应该发送到聊天室。

notification_channel.ex

  def handle_in("new:group:recommendation", msg, socket) do
    payload = %{
        message: msg["message"],
        url: msg["url"],
        title: msg["title"],
        user_name: get_name_of_user(socket.assigns.user_grapqhl_id),
        user_grapqhl_id: socket.assigns.user_grapqhl_id
    }

    IO.puts "incomming"
    IO.inspect msg
    Enum.map(msg["groups"], fn(x) ->
        App.Endpoint.broadcast_from! self(), "chat:"<>x,
            "new:recommendation", payload
        end)
    {:reply, :ok, socket}

  end

chat_channel.ex

 def handle_in("new:recommendation", msg, socket) do
      IO.puts "i am a recommendation !"
      IO.inspect msg
      chat_msg = %{
         "creator_id" => msg["user_grapqhl_id"],
         "text" => msg["message"],
         "creator_name" => msg["user_name"]
      }

     broadcast! socket, "new:msg", create_chat_msg(chat_msg,socket)
     {:reply, :ok, socket}
  end

测试

  test "do we send a new:recommendation to chat ?", %{guardian_token: guardian_token} do
      nils_base_64 = Base.encode64("user:nils")

      {:ok, socket} = connect(UserSocket, %{})
      {:ok, _, socket1} = subscribe_and_join(socket, "notifications:"<>nils_base_64, %{"guardian_token" => guardian_token})
      {:ok, _, socket} = subscribe_and_join(socket1, "chat:Y2hhdDpjaGF0Mw==", %{"guardian_token" => guardian_token})

      payload = %{
          "message" => "look at this cool thing!",
          "url" => "link to stuff",
          "title" => "AWESOME EVENT",
          "groups" => ["Y2hhdDpjaGF0Mw==", "Y2hhdDpwdWJsaWM="]
      }

      reply = %{message: "look at this cool thing!", title: "AWESOME EVENT", url: "link to stuff", user_grapqhl_id: nils_base_64, user_name: "Nils Eriksson"}

      ref = push socket1, "new:group:recommendation", payload
      assert_reply ref, :ok
      assert_broadcast "new:recommendation", ^reply
  end

此测试通过,我可以通过更改 reply 使其失败 或评论广播。通过将handle_in 更改为在chat_channel 中接收fail:please,我无法让它失败。 如果我发送更改,这就是它会抱怨的事情 ref = push socket1, "new:group:recommendation", payload ref = push socket, "new:group:recommendation", payload 在这种情况下并不令人惊讶。

这就是电线上的东西。

     Process mailbox:
   %Phoenix.Socket.Message{event: "init:msgs", payload: %{messages: []}, ref: nil, topic: "chat:Y2hhdDpjaGF0Mw=="}
   %Phoenix.Socket.Broadcast{event: "new:recommendation", payload: %{message: "look at this cool thing!", title: "AWESOME EVENTs", url: "link to stuff", user_grapqhl_id: "dXNlcjpuaWxz", user_name: "Nils Eriksson"}, topic: "chat:Y2hhdDpjaGF0Mw=="}
   %Phoenix.Socket.Message{event: "new:recommendation", payload: %{message: "look at this cool thing!", title: "AWESOME EVENTs", url: "link to stuff", user_grapqhl_id: "dXNlcjpuaWxz", user_name: "Nils Eriksson"}, ref: nil, topic: "chat:Y2hhdDpjaGF0Mw=="}

我使用通道身份验证,因为我使用的 elm 包还不支持套接字级别的身份验证。所以这就是chat中的样子

  def join("chat:" <> chat_id, %{"guardian_token" => token}, socket) do
  IO.puts chat_id
  case sign_in(socket, token) do
     {:ok, authed_socket, _guardian_params} ->
         Process.flag(:trap_exit, true)
         send(self, {:after_join})
         [_type, node_chat_id] = Node.from_global_id(chat_id)
         {:ok, assign(authed_socket, :chat_id, node_chat_id)}
     {:error, reason} ->
         IO.puts "Can't join channel cuz: " <> reason
       # handle error TODO
   end

结束

【问题讨论】:

    标签: sockets elixir phoenix-framework phoenix-channels


    【解决方案1】:

    在您的聊天频道主题中使用App.Endpoint.broadcast topic, event, payload。它应该可以工作。

    【讨论】:

      【解决方案2】:

      由于您在Endpoint 中使用broadcast_from/4。您应该在chat_channel 中使用handle_info/2

      alias Phoenix.Socket.Broadcast
        ...
      
      def handle_info(%Broadcast{topic: _, event: ev, payload: payload}, socket) do
          IO.puts ev
          IO.inspect payload
          # do something with ev and payload( push or broadcast)
          {:noreply, socket}
        end
      

      或者您可以从您的客户端监听该事件:

      chatChannel.on("new:recommendation", resp => {
         // doSomething with response
      }
      

      编辑:

      让我们稍微解释一下channelPubSub 系统的工作原理。

      当您想广播或推送带有有效负载的事件时。首先它将发送到PubSub系统,然后PubSub系统将其发送到所有订阅者进程(channel),主题为@ 987654332@ 注册到PubSub 系统。

      当您使用Endpoint.broadcast_from/4 从您的服务器广播事件时。PubSub 系统将接收带有有效负载的事件并将该事件广播到频道注册的主题。

      频道会触发handle_out回调并将消息推送给客户端。 所以在你的chat_channel 中你不需要handle_in "new:recommendation" 事件。你的客户只需要听那个事件。

      chatChannel.on("new:recommendation", resp => {
         // do something with response
      }
      

      让我重写你的测试:

      setup do
          nils_base_64 = Base.encode64("user:nils")
          {:ok, socket} = connect(UserSocket, %{})
          {:ok, _, socket} = subscribe_and_join(socket, "notifications:"<>nils_base_64, %{"guardian_token" => guardian_token})
          {:ok, socket: socket}
        end
      
      
      test "do we send a new:recommendation to chat ?", %{socket: socket} do
            MyApp.Endpoint.subscribe("chat:Y2hhdDpjaGF0Mw==")
      
            payload = %{
                "message" => "look at this cool thing!",
                "url" => "link to stuff",
                "title" => "AWESOME EVENT",
                "groups" => ["Y2hhdDpjaGF0Mw==", "Y2hhdDpwdWJsaWM="]
            }
      
      
      
            reply = %Phoenix.Socket.Broadcast{message: "look at this cool thing!",
                    title: "AWESOME EVENT",
                    url: "link to stuff",
                    user_grapqhl_id: nils_base_64,
                    user_name: "Nils Eriksson"}
      
            ref = push socket, "new:group:recommendation", payload
            assert_reply ref, :ok
            assert_receive ^reply
        end
      

      通过subscribe 到您想收听的主题,您可以确保您的频道收到带有assert_receive 的消息。 这就是将broadcast 测试到不同频道的方法。

      试一试告诉我。测试会通过的。

      【讨论】:

      • 我有频道授权重要吗?当我尝试这个时没有任何改变。我已经设法订阅了外部频道,不惜一切代价。
      • 哦,你的测试已经通过了。那么问题出在哪里?我以为你不能广播到不同的频道?
      • 是的,他们通过了,但他们不测试他们是否在聊天频道中收到。消息已广播但未接听。
      • 我编辑了答案。你可以试试告诉我
      • Tnx 很多,但感觉好像我错过了我想要做的事情。我有一个通知频道,当收到某些通知时,我想向聊天频道发送一条消息并说“嘿,我刚收到一个新的:组:推荐,把它转换成聊天:消息”我不想要将 new:group:recommendation 发送给客户端,只是发送到另一个我可以将其转换为聊天消息的频道。
      猜你喜欢
      • 2017-06-01
      • 2018-12-24
      • 2018-03-03
      • 2016-01-31
      • 1970-01-01
      • 2021-11-15
      • 2021-07-15
      • 2019-08-28
      • 2017-10-20
      相关资源
      最近更新 更多