Elixir Phoenix递归函数停止页面加载

时间:2016-09-28 16:23:30

标签: elixir phoenix-framework

我正在使用Phoenix elixir构建Web应用程序,我的Web应用程序需要加载索引页面,而不是在后台等待接收消息。这是我有问题的代码

defmodule ApplicationB.PageController do
  use ApplicationB.Web, :controller
  use AMQP

  def index(conn, _params) do
    {:ok, connection} = AMQP.Connection.open
    {:ok, channel} = AMQP.Channel.open(connection)
    AMQP.Queue.declare(channel, "hello")
    AMQP.Basic.consume(channel, "hello", nil, no_ack: true)
    IO.puts " [*] Waiting for messages. To exit press CTRL+C, CTRL+C"

    wait_for_messages

    render conn, "index.html"
  end

  def wait_for_messages do
    receive do
      {:basic_deliver, payload, _meta} ->
        IO.puts " [x] Received #{payload}"
        ApplicationB.Endpoint.broadcast! "message", "hello", %{body: "poruka"}
        wait_for_messages
    end
  end

end

我知道我的问题在我的wait_for_messages函数中,因为当我在index中调用wait_for_messages时它是递归函数,它永远不会到达render conn, "index.html"行。有没有办法使它工作,以便可以加载页面inde.html并在后台运行wait_for_messages?

2 个答案:

答案 0 :(得分:0)

您似乎在寻找Task模块。

为防止wait_for_messages / 0阻止您的操作,您可以使用Task.start_link/1,如下所示:

def index(conn, _params) do
  {:ok, connection} = AMQP.Connection.open
  {:ok, channel} = AMQP.Channel.open(connection)
  AMQP.Queue.declare(channel, "hello")
  AMQP.Basic.consume(channel, "hello", nil, no_ack: true)
  IO.puts " [*] Waiting for messages. To exit press CTRL+C, CTRL+C"

  Task.start_link(fn -> wait_for_messages end)

  render conn, "index.html"
end

答案 1 :(得分:0)

也许Phoenix Channels更适合这种情况。向客户端发送index.html,然后从该客户端应用程序中加入一个从AMQP总线发送消息的通道(将其广播到所有连接的客户端)。这将使您的应用程序以更加分散的方式实现免费的功能。文档在这里:http://www.phoenixframework.org/docs/channels

至于IO.puts ......我不清楚控制台输出的目的......更多的Elixir-y方法是让一个进程执行AMQP消息传递而另一个进程是你可以从消耗来自它的消息的iex控制台开始/交互,并提供一个API来停止(例如杀死)AMQP处理器。

..但是就目前而言,依靠控制台输出一次限制你进行一次这样的交互...而且Web服务本质上不是那种东西。