【React】EventEmitter2でイベント駆動型プログラミングをやってみよう

# はじめに

## EventEmitter2とは

EventEmitter2とはイベント駆動型プログラミングをサポートするためのライブラリ。Reactの状態管理にも使われる。

https://www.npmjs.com/package/eventemitter2

## EventEmitter vs. EventEmitter2

EventEmitter2ではリスナーの登録の削除を **off**で行える。
また、ワイルドカードを使用することができるなど、EventEmitter2はEventEmitterを拡張したライブラリである。

# 使い方

## インストール

```
npm i eventemitter2
```

## 初期設定

```jsx
import EventEmitter2 from 'eventemitter2';
// オプションの設定(ここではワイルドカードの使用を許可する)
const options = {wildcard: true,}
// インスタンスの作成
const emitter = new EventEmitter2(options);
```

### オプション一覧

| オプション名                  | デフォルト|        説明                           |
|------------------------------|--------------------------------|------------------------------|
| wildcard                   |false| ワイルドカードを使用する場合は **true** に設定する。 |
| delimiter                  | '.'|名前空間を区切るために使用する区切り記号を指定する。|
| newListener                |false |newListenerイベントを発生させる場合は **true** に設定する。    |
| removeListener             |false |removeListenerイベントを発生させる場合は **true** に設定する。 |
| maxListeners               | 10 |イベントに割り当てることができる最大リスナー数を指定。          |
| verboseMemoryLeak          |false |メモリリークメッセージでイベント名を表示する場合は **true** に設定する。|
| ignoreErrors               |false |エラーイベントがリスナーを持たない場合に、uncaughtException をスローしないようにする場合は **true** に設定する。   |

## イベント作成

ここでは簡単なイベント(リスナー)を作成する。

```jsx:sample①
const listener = () => {
  console.log('発火しました！');
};
```

引数がある例も作っておく。

```jsx:sample②
const listener = (data) => {
  console.log(`発火しました! Data : ${data}`);
}
```

## リスナーの登録

onで指定したイベントにリスナーを登録できる。
第一引数がkeyとなって、第２引数にイベントをしてする。

```jsx:sample①
emitter.on('eventName', listener);
```

```jsx:sample②
emitter.on('eventName2', listener2);
```

## イベントの発火

emitするとonで受信してイベント(リスナー)が発火する。
第１引数に指定したkeyに該当するものだけ発火する。


```jsx
emitter.emit('eventName');
```

第２引数にはリスナーに渡す引数が入る。

<p class="codepen" data-height="300" data-theme-id="dark" data-default-tab="html,result" data-slug-hash="YzJoKwq" data-user="odlqzyes-the-sans" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/odlqzyes-the-sans/pen/YzJoKwq">
  EventEmitter2</a> by Tomoki Ota (<a href="https://codepen.io/odlqzyes-the-sans">@odlqzyes-the-sans</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

## リスナーの登録の削除

リスナーの登録の削除は **off** か **removeListener** で削除できる。

```jsx
emitter.removeListener('eventName', listener);
emitter.off('eventName', listener);
```

```jsx
emitter.on('eventName', listener);
emitter.off('eventName', listener);
emitter.emit('eventName'); // 発火しない
```

**removeAllListeners** を使用すると全てのリスナーの登録を削除できる。

```jsx
removeAllListeners('eventName')
```
## イベントの受信(1回だけ)

onceを使うとイベントの受信は1回しか行われない。

```jsx
emitter.once('eventName', listener);
```

onの場合、emitの数だけ発火する。

```jsx:on
emitter.once('eventName', listener);
emitter.emit('eventName'); // 発火しました！
emitter.emit('eventName'); 
emitter.emit('eventName'); 
// 1回だけ発火する
```

それに対してonceはemitが何回行われても1回しか発火しない。

```jsx:once
emitter.once('eventName', listener);
emitter.emit('eventName'); // 発火しました！
emitter.emit('eventName'); // 発火しました！
emitter.emit('eventName'); // 発火しました！
// 3回発火する
```

## イベントの受信(n回)

manyを使うとイベントの受信回数を制限できる。

```jsx
emitter.many('eventName', 2, listener);
emitter.emit('eventName'); // 発火しました！
emitter.emit('eventName'); // 発火しました！
emitter.emit('eventName'); 
emitter.emit('eventName');
// 2回発火する
```

## APIまとめ

| メソッド名                  | 説明                                        |
|-------------------------|----------------------------------------------------|
| on(eventName, listener)           | 指定されたイベントにリスナー関数を登録する。    |
| once(eventName, listener)         | 一度だけ呼び出されるリスナー関数をイベントに登録する     |
| emit(eventName, [args...])        | オプションの引数を伴ってイベントを発火する。             |
| removeListener(eventName, listener) | 指定されたイベントからリスナーを削除する      |
| removeAllListeners([eventName])    | 指定されたイベントからすべてのリスナーを削除する  |
| listeners(eventName)              | 指定されたイベントのリスナーの配列を取得。           |
| setMaxListeners(n)                 | イベントごとの最大リスナー数を設定する。    |
| getMaxListeners()                  | イベントごとの最大リスナー数を取得。    |
| listenerCount(eventName)               | 指定されたイベントに登録されているリスナーの数を取得。           |

# Reactでの状態管理

EventEmitter2ではなく、EventEmitterですが、以下を参考にしてください。

[今から始めるReact入門 〜 flux編](https://qiita.com/TsutomuNakamura/items/cb3b6109fb21730cd73f#store-%E3%81%AE%E4%BD%9C%E6%88%90)
[Event Emitter instead of lifting state up in React](https://medium.com/@krzakmarek88/eventemitter-instead-of-lifting-state-up-f5f105054a5)

# 参考文献


1. [eventemitter2 - npm](https://www.npmjs.com/package/eventemitter2)
1. [EventEmitter2](http://adilapapaya.com/docs/eventemitter2/)
1. [Node.jsのEventEmitterでイベント駆動プログラミングをする](https://www.whizz-tech.co.jp/1659/#error_listener)