menu

Node.jsのEventEmitterでイベント駆動プログラミングをする

公開日:2019年07月31日 カテゴリー:JavaScript, Node.js, 開発

はじめに

今回はNode.jsでイベント駆動のプログラミングを行う際に使われる、EventEmitterを紹介します。

イベント駆動のプログラミングとは、順次に処理が実行されるのではなく、なんらかのイベントによってあらかじめ指定された処理が実行されるようなプログラミングの手法です。

クライアントサイドのJSに馴染みがある方は、DOM要素のイベントにコールバックを設定した事があると思いますが、それがまさにイベント駆動のプログラミングです。

今回はサーバーサイドのJSで、イベント駆動のプログラミングを行う方法を解説します。

EventEmitter とは

Node.js のコアライブラリで、イベント駆動のパラダイムでのプログラミングをサポートするライブラリです。

EventEmitter 自体のインスタンスを生成して使ったり、任意のクラスで継承して使うことができます。

EventEmitter を継承することで、event に listener を登録する EventEmitter#on や、event を発火させる EventEmitter#emit が利用できるようになります。

イベント駆動が必要な多くのライブラリで用いられています。

EventEmitter の API

  • EventEmitter#defaultMaxListeners
  • EventEmitter#on(eventName, listener)
  • EventEmitter#once(eventName, listener)
  • EventEmitter#emit(eventName, […args])
  • EventEmitter#eventNames()
  • EventEmitter#getMaxListeners()
  • EventEmitter#setMaxListeners(n)
  • EventEmitter#listeners(eventName)
  • EventEmitter#listenerCount(eventName)
  • EventEmitter#prependListener(eventName, listener)
  • EventEmitter#prependOnceListener(eventName, listener)
  • EventEmitter#removeAllListener(eventName)
  • EventEmitter#removeListener(eventName, listener)

EventEmitter#on

listner を登録するために使われるメソッドです。

第 1 引数の eventName に紐づけて、第 2 引数の listener を登録します。

  • eventName
  • listener

EventEmitter#emit

event を発火させるために使われるメソッドです。

第 1 引数の eventName に紐づく event に登録されている全ての lisnter を、同期的に呼び出します。

その際には、第 2 引数以降の args を引数として渡し、返り値は無視します。

また、呼び出される順番は、単に登録された順番です。

  • eventName
  • [args]

EventEmitter#once

一度だけ呼び出される listener を登録するために使われるメソッドです。

EventEmitter#on と同様、第 1 引数の eventName に紐づけて、第 2 引数の listener を登録します。

このメソッドを使って登録された listener は、1 度実行されたら、2 回目以降の event の発火では無視されます。

EventEmitter#eventNames

listener が登録されているすべてのイベントの名前を要素にもつ配列を返します。

要素の型は、文字列またはシンボルです。

EventEmitter#listeners

第 1 引数の eventName に紐づくすべての listner を返します。

EventEmitter#listenerCount

第 1 引数の eventName に紐づくすべての listner の数を返します。

EventEmitter#prependListener

第 1 引数の eventName に登録されている listeners の内部リストの先頭に第 2 引数の listener を追加します。

EventEmitter#removeAllListeners

第 1 引数の eventName に登録されている全ての listeners を取り除きます。

EventEmitter#removeListener

第 1 引数の eventName に登録されている、第 2 引数の listener を取り除きます。

状況ごとのサンプルコード

イベントの登録と発火

EventEmitter#on で登録した listner を EventEmitter#emit で呼び出します。

this の扱い

EventEmitter#on で登録された listner の内部のthisは、通常は付属の EventEmitter を指します。

ただし、Allow 関数を使うことで、thisを束縛することができます。

同期実行と非同期実行

EventEmitter は、全ての listener を登録された順に同期的に呼び出します。

これは、イベントに順序付けを行うことで、競合またはロジックエラーを回避するです。

ただし、適切な場合にsetImmediate()process.nextTick()を呼び出すことで、listner を非同期に実行することもできます。

listner を一度だけ実行する

EventEmitter#on を使って登録された listner は、その event が発火されたタイミングで、何度でも実行されます。

もしも、listner を一度だけ実行したい場合、EventEmitter#once を使って listener を登録します。

EventEmitter#on で登録した場合

EventEmitter#once で登録した場合

Error イベント

EventEmitter のインスタンス内部でエラーが起きた場合、errorイベントが発火されます。

これは、Node.js に特殊なケースとして処理されます。

error イベントに登録された listener が存在しない場合

errorイベントが発火されると、error が投げられ、スタックトレースが出力され、Node.js のプロセスが終了します。

error イベントには listener を登録する

少なくとも 1 つの listener を、errorイベントに登録しておくことが推奨されます。

errorイベントに登録された listner は、エラー発生時のオブジェクトを第 1 引数で受け取ることができます。

newListener イベント

EventerEmitter は、リスナーを追加する前に newListner イベントを発火します。

この時、新たに登録される eventName と、listener が、newListener イベントに登録されている listener に渡されます。

removeListener イベント

EventerEmitter は、リスナーが除去された後に removeListner イベントを発火します。

この時、直前に登録された eventName とlistener が、newListener イベントに登録されていた listener に渡されます。

 

イベント駆動のプログラミングのまとめ、いかがでしたでしょうか?

最後までお読みくださり、ありがとうございました!

 

■参考資料

 

☆☆☆ 新しいことにチャレンジしたい!仲間と一緒に成長したい!やりがいのある仕事で充実した毎日を過ごしたい!そんな熱意をお持ちの方、私たちと一緒に働きませんか?ウィズテクノロジーでは一緒に働いていただけるエンジニアを大阪・東京で募集しています。☆☆☆