GenEvent 是事件處理的通用部分的抽象。
經過 GenEvent ,咱們給已有的服務 動態 的添加 事件處理。html
以前已經介紹了 GenServer ,GenServer 和 GenEvent 的主要區別在於:ios
基於上述的區別,GenEvent 和 GenServer 的應用場景也不一樣。服務器
經過 GenEvent 建立一個事件管理器,將此事件管理器添加到現有進程中,現有進程就有了處理相應事件的能力。異步
簡單示例以下:測試
defmodule HelloEvent do use GenEvent def handle_event(event, parent) do case event do :hello -> send parent, :world :world -> send parent, :hello _ -> send parent, "error msg" end {:ok, parent} end end
測試過程:spa
# 啓動一個空的事件管理器 iex(1)> {:ok, manager} = GenEvent.start_link {:ok, #PID<0.87.0>} # 發送 :hello 消息 iex(2)> GenEvent.sync_notify(manager, :hello) :ok # 沒有任何反應,由於事件管理器中沒有任何 handle 來處理消息 iex(3)> flush :ok # 給事件管理器增長一個handle,同時將當前進程PID做爲事件處理的狀態 iex(4)> GenEvent.add_handler(manager, HelloEvent, self()) :ok # 發送 :hello 消息 iex(5)> GenEvent.sync_notify(manager, :hello) :ok # 事件管理器處理了 :hello 消息,並返回 :world 結果 iex(6)> flush :world :ok # 發送 :world 消息 iex(7)> GenEvent.sync_notify(manager, :world) :ok # 事件管理器處理了 :world 消息,並返回 :hello 結果 iex(8)> flush :hello :ok # 發送 :test 消息 iex(9)> GenEvent.sync_notify(manager, :test) :ok # 事件管理器對於 :hello 和 :world 之外的消息都返回 "error msg" iex(10)> flush "error msg" :ok
上面測試中用的發送消息的方法都是同步方式 sync_notify ,經過異步方式 notify 發送消息也是同樣的, GenEvent 的 handle_event 接收同步和異步的消息。code
事件流就是將 GenEvent 的事件轉入到流中,這樣,就能夠經過處理流的方式來處理事件。server
好比上面的例子,經過 GenEvent 的 stream ,能夠不定義 defmodule HelloEvent 也實現上面的功能。htm
上述測試過程能夠改成以下:blog
iex(1)> {:ok, manager} = GenEvent.start_link {:ok, #PID<0.59.0>} iex(2)> stream = GenEvent.stream(manager) %GenEvent.Stream{manager: #PID<0.59.0>, timeout: :infinity} iex(3)> nil iex(4)> spawn_link fn -> ...(4)> for x <- stream do ...(4)> case x do ...(4)> :hello -> IO.inspect :world ...(4)> :world -> IO.inspect :hello ...(4)> _ -> IO.inspect "error msg" ...(4)> end ...(4)> end ...(4)> end #PID<0.71.0> iex(5)> GenEvent.sync_notify(manager, :hello) :world :ok iex(6)> GenEvent.sync_notify(manager, :world) :hello :ok iex(7)> GenEvent.sync_notify(manager, :test) "error msg" :ok
能夠看出,咱們沒有給 GenEvent 綁定任何的 handler,而是在 GenEvent 的事件流中對全部消息進行了處理。
GenEvent 中事件流的特性是 erlang 中所沒有的。
除了上面用的 handle_event 和 stream, GenEvent 中還有其餘的實用的 Functios 和 Callbacks
具體參見:http://elixir-lang.org/docs/stable/elixir/GenEvent.html