0

我正在尝试创建一个仅包含用户可以订阅的时钟的 Phoenix 频道。

defmodule MyWeb.TimeChannel do
  use Phoenix.Channel
  def join("room:time", _message, socket) do
    schedule_heartbeat()
    {:ok, socket}
  end

  def handle_info(_, socket) do
    broadcast!(socket, "update", %{time: DateTime.utc_now()})
    schedule_heartbeat()
    {:noreply, socket} 
  end

  @heartbeat_ms 1000
  defp schedule_heartbeat, do: Process.send_after(self(), :heartbeat, @heartbeat_ms)

end

我遇到的问题是,当多个客户端加入时,我最终会每秒安排多个滴答声。

我怎样才能只安排一个滴答作响的时钟?

4

1 回答 1

2

我通过创建一个单独的 GenServer 来解决这个问题,该 GenServer 发布到频道:

defmodule MarsWeb.TimeServer do
  use GenServer

  def start_link(_) do
    GenServer.start_link(__MODULE__, %{}, name: :time_server )
  end

  def child_spec(arg) do
    %{
      id: __MODULE__,
      start: {__MODULE__, :start_link, [arg]},
      restart: :permanent,
    }
  end

  @impl true
  def init(_) do
    schedule_tick()
    {:ok, %{}}
  end

  @impl true
  def handle_info(:tick, state) do
    MarsWeb.Endpoint.broadcast!("room:time", "update", %{time: DateTime.utc_now()})
    schedule_tick()
    {:noreply, state} 
  end

  @tick_ms 1000
  defp schedule_tick, do: Process.send_after(self(), :tick, @tick_ms)

end
于 2020-04-22T07:44:10.317 回答