[Javascript] イベント駆動型の設計ができるEventEmitterに入門
こんにちは、@yoheiMuneです。
今日はNodeJSやフロントJSで利用可能な、EventEmitterを使った、イベント駆動な実装方法をブログに書きたいと思います。
また、BabelでフロントエンドビルドやWebpackでフロントエンドビルドを使えば、フロントエンドでも
という感じで使います。説明だけだとわかりづらいと思いますので、コードベースで見てみたいと思います。
ただ上記のような単独で使うことは少ないように思います。EventEmitterを継承したクラスやオブジェクトで使うことが多いと思いますので、次章ではそれを扱ってみたいと思います。
https://github.com/yoheiMune/frontend-playground/tree/master/011-eventemitter
Events | Node.js v7.4.0 Documentation
node.jsのEventEmitterについてのメモ書き - 株式会社BEFOOL
Node書くならEventEmitterについて知っとくべし - Qiita
最後になりますが本ブログでは、フロントエンド・Go言語・Node.js・Python・Linux・開発関連・Swift・Java・機械学習など雑多に情報発信をしていきます。自分の第2の脳にすべく、情報をブログに貯めています。気になった方は、本ブログのRSSやTwitterをフォローして頂けると幸いです ^ ^。
最後までご覧頂きましてありがとうございました!
今日はNodeJSやフロントJSで利用可能な、EventEmitterを使った、イベント駆動な実装方法をブログに書きたいと思います。
目次
本記事を試すための環境
この記事の内容は、nodejsで動作します。新し目のバージョンでお試しください(僕の環境ではv6.2.2で動作確認しています)。また、BabelでフロントエンドビルドやWebpackでフロントエンドビルドを使えば、フロントエンドでも
EventEmitterを利用可能です(いくつかのプロジェクトで利用されているのを見かけたことがあります)。EventEmitterとは
EventEmitterは直訳の通り、イベントを発火することができる機能で、主に「イベントを発火する人」と「イベントを受け取る人」の大きく2つに使い方が分かれます。具体的には、イベントを発火する人
| 関数名 | 説明 |
|---|---|
| emit | イベントを発火してデータを渡す |
イベントを受け取る人
| 関数名 | 説明 |
|---|---|
| on | イベントが発火されたらデータを受け取る |
| once | onと同じだが発火されるのは1回だけ |
EventEmitterの基本的な使い方
コードでは、以下のように利用することができます。
// app.js
// EventEmitterをrequireで読み込む
const EventEmitter = require('events').EventEmitter;
// EventEmitterのインスタンスを作成する
const ev = new EventEmitter();
// 01. イベントを受け取る人
//=======================================
// イベントを受け取る
ev.on('data', data => {
console.log('dataを受け取ったよ:', data);
})
// イベントを受け取る(1回限り)
ev.once('data', data => {
console.log('dataを受け取ったよ(1回限り):', data);
});
// イベントを発行する人
//=======================================
ev.emit('data', 1);
ev.emit('data', 2);
ev.emit('data', 3);
上記を実行すると以下のように出力されます。$ node app.js dataを受け取ったよ: 1 dataを受け取ったよ(1回限り): 1 dataを受け取ったよ: 2 dataを受け取ったよ: 3と、こんな感じでEventEmitterを使うことができます。
ただ上記のような単独で使うことは少ないように思います。EventEmitterを継承したクラスやオブジェクトで使うことが多いと思いますので、次章ではそれを扱ってみたいと思います。
EventEmitterの実践的な使い方
ここではEventEmitterを継承したクラスでの使い方のサンプルを書きたいと思います。以下のクラスは指定したディレクトリ(フォルダ)にあるファイルを読み込むサンプルです。
// app2.js
// EventEmitterをrequireで読み込みます。
const EventEmitter = require('events').EventEmitter;
// ファイル操作に使うモジュールも読み込みます。
const fs = require('fs');
const path = require('path');
//*******************************
// 1. EventEmitterを継承したクラスを作成します。
//*******************************
class DirectoryReader extends EventEmitter {
constructor(targetDirectory) {
super();
this.dir = targetDirectory;
}
read() {
fs.readdir(this.dir, (err, files) => {
if (err) {
//*******************************
// 2. エラーが発生した場合に、errorイベントを発火します.
//*******************************
return this.emit('error', err);
}
files.forEach(file => {
//*******************************
// 3. データを読み込んだら、dataイベントを発火します。
//*******************************
let content = fs.readFileSync(path.join(this.dir, file), 'utf-8');
this.emit('data', file, content);
});
//*******************************
// 4. 処理が終わったらendイベントを発火します.
//*******************************
this.emit('end');
});
}
}
//*******************************
// 5. EventEmitterを継承したクラスのインスタンスを生成します.
//*******************************
let dirReader = new DirectoryReader('./sampledir');
//*******************************
// 6. EventEmitterを継承しているので、onでイベントを登録できます.
//*******************************
dirReader.on('error', err => {
console.log('エラーだよ。 ', err);
});
dirReader.on('data', (fileName, content) => {
console.log(`データを受け取ったよ。fileName=${fileName}, content=${content}`);
});
dirReader.once('data', (fileName, content) => {
console.log(`1回だけデータを受け取ったよ。fileName=${fileName}, content=${content}`);
});
dirReader.on('end', () => {
console.log('終わったよ。');
});
dirReader.read();
上記を実行すると、例えば以下のようになります(サンプルコードは後述のGithubレポジトリにあります)。$ node app2.js データを受け取ったよ。fileName=aaa.txt, content=aaaaaaaaa 1回だけデータを受け取ったよ。fileName=aaa.txt, content=aaaaaaaaa データを受け取ったよ。fileName=bbb.txt, content=bbbbbbbbbbb データを受け取ったよ。fileName=ccc.txt, content=ccccccccccccc 終わったよ。ちょっと長くなってしまいましたが、
EventEmitterを継承することでemitやonが使えるようになり、イベント駆動な実装ができるようになります。使いこなせるようになると便利ですね。サンプルコード
上記のサンプルコードは下記にありますので、必要あればお試しください。https://github.com/yoheiMune/frontend-playground/tree/master/011-eventemitter
参考資料
EventEmitterを学ぶために以下の記事を参考にしました。ありがとうございます。Events | Node.js v7.4.0 Documentation
node.jsのEventEmitterについてのメモ書き - 株式会社BEFOOL
Node書くならEventEmitterについて知っとくべし - Qiita
最後に
EventEmitterが使われているのは何度かみたことがあったんですが、使うのはほぼ初めてなので学んでみようと思い今回のブログを書きました。JavaScriptは、Promiseを用いた非同期処理での実装が流行っていますが、前からあるEventEmitterもいいですね。それぞれ使いこなせるようになりたい今日この頃です。最後になりますが本ブログでは、フロントエンド・Go言語・Node.js・Python・Linux・開発関連・Swift・Java・機械学習など雑多に情報発信をしていきます。自分の第2の脳にすべく、情報をブログに貯めています。気になった方は、本ブログのRSSやTwitterをフォローして頂けると幸いです ^ ^。
最後までご覧頂きましてありがとうございました!





