2015-12-30 55 views
1

如果用户已加入主题,说"rooms:lobby",然后用户加入同一频道上的另一个子主题,如"rooms:party"。我如何强制用户从后端离开“房间:大厅”。我尝试过滤广播,但没有任何运气。我宁愿通过过滤广播来终止与旧的子主题的连接。Phoenix:一次只允许订阅一个频道上的一个子主题

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 

我知道这是可以从前端离开的话题,但我需要确保只有他们正在查看自己当前主题得到有效载荷,而不是任何以前的主题,其中订阅了一特定频道。

+1

我不知道我按照你的问题。每个主题将在不同的过程中以不同的渠道运行。因此,考虑到上面的代码,如果您使用的是“房间:1”和“房间:3”,即使它们使用相同的逻辑,它们也会完全分开。所以如果你想让用户离开,你可以返回来自任何事件的'{:stop,:normal,:ok,:state}'或类似的东西。 –

+0

让我给出更多的上下文。该应用程序正被用于推送通过RPC从Rails应用程序发送到通过反应/流量构建的SPA的通知。如果这是一个香草请求/响应REST应用程序,更改路由将重新加载页面并更新套接字连接,则使用正确的ID加入子主题。我假设在这一点上旧的连接和主题订阅将会丢失。我试图通过SPA上的路线更改实现相同的行为。 –

+0

我用'gen_server'解决了这个问题,它跟踪最近加入的子主题,然后在'handle_out'中发送一个离开事件,告诉客户端离开它是一个旧的子主题,而不是原来的有效载荷。这感觉喜欢它不是处理这个最合适的方法。 –

回答

1

从您的评论中可以看出,您尝试每条路线加入1个频道,并且您希望在路线改变时切换频道而不是累积多个频道。我猜你是从高级React组件中加入生命周期方法(例如ComponentWillMount)中的通道。

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

+0

我最终做了类似的事情,在路由器转换回调中添加了'join'和'leave'。 –