#elixir #phoenix-framework
#эликсир #phoenix-фреймворк
Вопрос:
Я пытаюсь прослушать сообщение в моем маршрутизаторе сокетов, отправить сообщение процессу в памяти, созданному модулю Runner, а затем передать результат клиенту.
За пределами Phoenix в автономном тестировании этот код работает. С Phoenix я получаю эту ошибку
~/chatroom:.mix phoenix.server
Compiling 2 files (.ex)
== Compilation error on file web/models/runner.ex ==
** (CompileError) web/models/runner.ex:8: undefined function send/3
(stdlib) lists.erl:1338: :lists.foreach/2
(stdlib) erl_eval.erl:670: :erl_eval.do_apply/6
(elixir) lib/kernel/parallel_compiler.ex:117: anonymous fn/4 in Kernel.ParallelCompiler.spawn_compilers/1
Мой lobby_channel.ex:
defmodule Chatroom.LobbyChannel do
require Runner
use Phoenix.Channel
{:ok, pid: spawn(fn -> Runner.input() end)}
def join("lobby", _payload, socket) do
{:ok, socket}
end
def handle_in("new_message", payload, socket) do
case payload["message"] do
"hello" -> broadcast! socket, "new_message", payload
"jump" -> send pid, {:jump, self, [avatar: avatar, socket: socket]}
_ -> nil
end
{:noreply, socket}
end
receive do
{:result, mover, socket} -> broadcast! socket, "new_message", [name: "State", message: "5"]
end
end
Runner.ex, сохраненный в web/models/runner.ex
defmodule Runner do
def spawn do
%{maxJump: 100}
end
def input do
receive do
{:run, sender, data} -> send sender, run(sender[:avatar]), data[:socket]
{:jump, sender, data} -> send sender, jump(sender[:avatar]), data[:socket]
end
input
end
defp run(mover) do
mover = case mover.y do
1 ->
Map.merge(mover, %{y: 0})
_ -> mover
end
Map.merge(mover, %{x: mover.x 1})
end
defp jump(mover) do
case {mover.y} do
{0} ->
Map.merge(mover, %{y: mover.y 1})
_ ->
mover
end
end
end
Почему я не могу отправлять эти сообщения?
Ответ №1:
Ошибка возникает в этом выражении, которое вызывает функцию send
с тремя аргументами:
send sender, run(sender[:avatar]), data[:socket]
Но send
функция принимает только два аргумента: процесс, которому нужно что-то отправить, и сообщение для отправки. Возможно, вы хотели встроить эти два элемента в кортеж? Вот так:
send sender, {run(sender[:avatar]), data[:socket]}
Существует send
функция, которая принимает три аргумента, а именно Process.send/3
. Его третьим аргументом является список опций. Для ее вызова необходимо явно указать имя модуля.