我正在尝试将 Phoenix 文档中的Phoenix.Channel.reply/2示例扩展为异步回复 Phoenix 通道/套接字推送事件的完整工作示例:
取自https://hexdocs.pm/phoenix/Phoenix.Channel.html#reply/2:
def handle_in("work", payload, socket) do Worker.perform(payload, socket_ref(socket)) {:noreply, socket} end def handle_info({:work_complete, result, ref}, socket) do reply ref, {:ok, result} {:noreply, socket} end
我对示例进行了如下修改:
room_channels.ex
...
def handle_in("work", job, socket) do
send worker_pid, {self, job}
{:noreply, socket}
end
def handle_info({:work_complete, result}, socket) do
broadcast socket, "work_complete", %{result: result}
{:noreply, socket}
end
...
工人.ex
...
receive do
{pid, job} ->
result = perform(job) # stub
send pid, {:work_complete, result}
end
...
该解决方案有效,但它不依赖于socket_ref(socket)
在Phoenix.Channel.reply/2上生成和传递 socket_ref 。相反,它依赖于Phoenix.Channel.broadcast/3。
该文档暗示,reply/2专门用于这种异步回复套接字推送事件的场景:
回复(arg1,arg2)
异步回复套接字推送。
当您需要回复无法使用 {:reply, {status, payload}, socket} 从您的 handle_in 回调返回的推送时很有用。reply/3 将用于极少数情况下,您需要在另一个进程中执行工作,并在完成时通过使用 socket_ref/1 生成对推送的引用来回复。
当我生成并传递一个 socket_ref,并依靠Phoenix.Channel.reply/2对套接字推送进行异步回复时,我根本无法让它工作:
room_channels.ex
...
def handle_in("work", job, socket) do
send worker_pid, {self, job, socket_ref(socket)}
{:noreply, socket}
end
def handle_info({:work_complete, result, ref}, socket) do
reply ref, {:ok, result}
{:noreply, socket}
end
...
工人.ex
...
receive do
{pid, job, ref} ->
result = perform(job) # stub
send pid, {:work_complete, result, ref}
end
...
我的 room_channels.exhandle_info
函数被调用,但reply/2似乎没有通过套接字发送消息。我看不到 stderr 上的堆栈跟踪或 stdout 上的任何输出以指示错误。更重要的是,跟踪 socket_ref 似乎只会给我的代码增加开销。
与我的广播/3解决方案相比,使用 socket_ref 和回复/2有什么好处?如何使回复/2的解决方案正常工作?