这两个概念经常连着出现,但职责不同。
#PubSub:广播网
Phoenix.PubSub 负责:
- 订阅主题
- 广播消息
- 跨节点扩散
最小用法非常直接:
children = [
{Phoenix.PubSub, name: City.PubSub}
]Phoenix.PubSub.subscribe(City.PubSub, "org:7:dispatches")
Phoenix.PubSub.broadcast(City.PubSub, "org:7:dispatches", {:dispatch_created, dispatch})这意味着:
- Context 可以广播
- LiveView 可以订阅
- Channel 可以订阅
- 其他普通进程也可以订阅
PubSub 是 Phoenix 城邦里最重要的“松耦合交通层”。
#Presence:在线名册
Presence 不是“聊天室专属功能”,本质上是:
跟踪谁在某个 topic 上在线,以及 join/leave diff。
定义 Presence 模块:
defmodule CityWeb.Presence do
use Phoenix.Presence,
otp_app: :city,
pubsub_server: City.PubSub
end在 Channel 里追踪:
def join("district:" <> district_id, _payload, socket) do
send(self(), :after_join)
{:ok, assign(socket, :district_id, district_id)}
end
def handle_info(:after_join, socket) do
topic = "district:#{socket.assigns.district_id}"
{:ok, _} =
CityWeb.Presence.track(
socket,
socket.assigns.current_user.id,
%{online_at: System.system_time(:second)}
)
push(socket, "presence_state", CityWeb.Presence.list(topic))
{:noreply, socket}
end客户端还能用官方 JS Presence helper 同步状态。
你可以把它想成:
PubSub = 城市广播喇叭
Presence = 进出登记簿一个负责“通知”,一个负责“谁在场”。