我使用Phoenix框架为我的Elixir应用程序与WebSocket连接。我有两个不同的主题,一个用于用户,另一个用于管理员。管理员应该看到哪些用户在场。我决定使用凤凰城的Presence
模块。不幸的是,您只能将当前Presence
状态发送到开始跟踪的套接字。
示例代码:
def join("users", params, socket) do
socket |> assign(:user_id, params[:user_id])
send(self, :after_join)
{:ok, socket}
end
def join("admins", _params, socket) do
{:ok, socket}
end
def handle_info(:after_join, socket) do
push(socket, "presence_state", Presence.list(socket))
{:ok, _} = Presence.track(socket, socket.assigns[:user_id], %{
online_at: inspect(System.system_time(:seconds))
})
{:noreply, socket}
end
我想在管理员的前端应用程序中监听状态更改中的事件。可以使用Phoenix.Presence
吗?
答案 0 :(得分:3)
您可以使用YourApp.Endpoint.broadcast/3
:
def handle_info(:after_join, socket) do
{:ok, _} = Presence.track(socket, socket.assigns[:user_id], %{
online_at: inspect(System.system_time(:seconds))
})
YourApp.Endpoint.broadcast "admins", "presence_state", Presence.list(socket)
{:noreply, socket}
end
并从您的adminChannel听取presence_state
:
adminChannel.on("presence_state", state => {
presences = Presence.syncState(state)
// doSomethingWithPresences
}
您应该将YourApp.AdminChannel
和YourApp.UserChannel
当您的客户收到presence_diff
个活动时。您可以将其推送到用户频道并再次使用Endpoint.broadcast/3
:
userChannel.on("presence_diff", diff => {
userChannel.push("presence_diff", diff)
}
YourApp.UserChannel
中的:
def handle_in("presence_diff", diff, socket) do
YourApp.Endpoint.broadcast "admins", "presence_diff", diff
{:noreply, socket}
end
现在你可以听你的presence_diff
事件了:
adminChannel.on("presence_diff", diff => {
presences = Presence.syncDiff(diff)
render(presences)
}
答案 1 :(得分:1)
如果您要在其中一个频道的回调处理程序(例如handle_info/2
)中设置状态跟踪,则可以对以下任意主题添加跟踪:
Presence.track(self(), "admins", socket.assigns[:user_id], %{some_metadata: "whatever"})
然后,在另一个进程的其他位置,您可以订阅admins
主题,如:
YourApp.Endpoint.subscribe("admins")
,此时该流程将开始接收presence_diff
条消息。