Websocket Phoenix:一次只允许订阅一个频道上的一个子主题

Websocket Phoenix:一次只允许订阅一个频道上的一个子主题,websocket,elixir,phoenix-framework,Websocket,Elixir,Phoenix Framework,如果用户加入了一个主题,请说“rooms:Lobble”,然后用户在同一频道上加入另一个子主题,如“rooms:party”。如何强制用户从后端离开“房间:大厅”。我试过过滤广播,但没有成功。我更愿意通过过滤广播来终止与旧子主题的连接 defmodule MyApp.RoomsChannel do use Phoenix.Channel intercept ["new_msg"] def join("rooms:" <> room_id, _params, socket

如果用户加入了一个主题,请说
“rooms:Lobble”
,然后用户在同一频道上加入另一个子主题,如
“rooms:party”
。如何强制用户从后端离开“房间:大厅”。我试过过滤广播,但没有成功。我更愿意通过过滤广播来终止与旧子主题的连接

defmodule MyApp.RoomsChannel do
  use Phoenix.Channel
  intercept ["new_msg"]

  def join("rooms:" <> room_id, _params, socket) do
    {:ok, assign(socket, :room_id, room_id)
  end

  def handle_out("new_msg", payload, socket) do
    if current_room?(socket.assigns[:room_id], socket.topic) do
      push socket, "new_msg", payload
      {:noreply,socket}
    else
      {:noreply, socket}
    end
  end

  defp current_room?(room_id, "rooms:" <> sub_topic) do
    room_id == sub_topic
  end
end
defmodule MyApp.RoomsChannel do
使用凤凰频道
截取[“新消息”]
def join(“房间:”房间id、_参数、插座)do
{:确定,分配(套接字,:房间id,房间id)
结束
def handle_out(“新消息”、有效负载、插座)do
如果当前房间?(socket.assigns[:room\u id],socket.topic)do
推动插座,“新信息”,有效负载
{:noreply,socket}
其他的
{:noreply,socket}
结束
结束
解除当前会议室?(会议室id,“会议室:”子主题)do
房间id==子主题
结束
结束

我知道可以从前端保留一个主题,但我需要确保只有他们当前正在查看的主题才能获得有效负载,而不是在某个特定频道上订阅的任何以前的主题。

从您的评论中,听起来好像您正试图加入每个频道的一个频道,并且您希望在以下情况下切换频道:n路线改变,而不是累积多个通道。我猜您是在从高级React组件加入生命周期方法(例如ComponentWillMount)中的通道


如果是这样,为什么不在ComponentWillUnmount中终止客户端的频道?这应该在客户端上的路由更改之前触发。

我不确定我是否遵循了您的问题。每个主题将在不同的频道中运行,在不同的进程中。因此,如果您在“rooms:1”和“rooms:3”上,请给出上述代码,它们将完全分开,即使它们使用相同的逻辑。因此,如果希望用户离开,可以返回
{:stop,:normal,:ok,:state}
或任何事件中的类似内容。让我给出更多上下文。该应用程序用于将通过RPC发送的通知从rails应用程序推送到使用react/flux构建的SPA。如果这是普通请求/响应REST应用程序,则更改路由将重新加载页面和更新套接字连接,然后使用正确的id。我假设此时旧的连接和主题订阅将丢失。我试图通过SPA上的路由更改实现相同的行为。我已经通过跟踪最近加入的子主题的
gen_服务器解决了这一问题,然后在
handle_out
中,我发送了一个休假事件告诉c“离开客户端”是一个旧的子主题,而不是原始的有效负载。这感觉似乎不是处理此问题的最合适的方式。我最后做了类似的事情,在路由器转换回调中添加了
join
leave