【发布时间】:2017-02-25 23:21:18
【问题描述】:
我正在尝试将 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
...
worker.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
...
worker.ex
...
receive do
{pid, job, ref} ->
result = perform(job) # stub
send pid, {:work_complete, result, ref}
end
...
我的 room_channels.ex handle_info 函数被调用,但 reply/2 似乎没有通过套接字发送消息。我看不到 stderr 上的堆栈跟踪或 stdout 上的任何输出以指示错误。更重要的是,跟踪 socket_ref 似乎只会给我的代码增加开销。
与我的 broadcast/3 解决方案相比,使用 socket_ref 和 reply/2 有什么好处,以及如何通过 reply/2 获得解决方案上班?
【问题讨论】:
标签: phoenix-framework phoenix-channels