Elixir官方指南中有类似代理的实现
defmodule AAgent do
def start_agent do
spawn_link fn -> loop(%{}) end
end
def loop(state \\ %{}) do
receive do
{:put, key, value, caller} ->
new_state = Map.put(state, key, value)
send caller, new_state
loop(new_state)
{:get, key, caller} ->
send caller, Map.get(state, key)
loop(state)
end
end
end
使用它时,响应将传递给其调用者进程邮箱
a = AAgent.start_agent
send a, {:put, :a, 42, self()}
flush
%{a: 42}
但是,当使用实际代理(内部使用GenServer
)时,父进程可立即使用响应
iex> Agent.get(agent, fn list -> list end)
["eggs"]
当我使用代理时,我不需要编写receive
块来获取["eggs"]
,结果已经可用,即使它是一个将数据传递给另一个进程的单独进程。是否可以使用裸流程实现相同的效果,或GenServer
使用其他内容?
答案 0 :(得分:4)
接收块在 play() {
this.wavesurfer.play();
}
功能内 - 您不需要手动编写。但基本原则完全相同。
答案 1 :(得分:4)
当我使用代理时,我不需要写一个接收块来获取[“eggs”],结果已经可用
你没有写接收,但是Agent.get
通过拨打receive
来调用GenServer.call
which contains the receive
间接做:gen.call
。只需4行代码即可为代理实现相同的功能:
defmodule AAgent do
def start_agent do
spawn_link fn -> loop(%{}) end
end
def loop(state \\ %{}) do
receive do
{:put, key, value, _caller} ->
new_state = Map.put(state, key, value)
loop(new_state)
{:get, key, caller} ->
send caller, Map.get(state, key)
loop(state)
end
end
def get(agent, key) do
send(agent, {:get, key, self()})
receive do x -> x end
end
end
a = AAgent.start_agent
send a, {:put, :a, 42, self()}
IO.inspect AAgent.get(a, :a)
输出:
42