イベントの発行とリスナー関数の登録
const EventEmitter = require('events').EventEmitter
const fs = require('fs')
function findPattern(files, regex) {
const emitter = new EventEmitter()
files.forEach(function(file) {
fs.readFile(file, 'utf8', (err, content) => {
if (err) {
// ファイル読み込みにエラーが発生した場合に通知するerrorイベントの生成
return emitter.emit('error', err)
}
// ファイル読み込みが完了した時点で通知するfilereadイベントの生成
emitter.emit('fileread', file)
let match
if (match = content.match(regex)) {
// 指定のパターンがファイル中に見つかった場合に通知するfoundイベントの生成
match.forEach(elem => emitter.emit('found', file, elem))
}
})
})
return emitter
}
/* -------------------------------------------------------------------------- */
findPattern(
[
'fileA.txt',
'fileB.json'
],
/hello \\w+/g
)
// onで特定のイベントに対してリスナー関数を登録
.on('fileread', file => console.log(file + ' was read'))
.on('found', (file, match) => console.log('Matched "' + match + '" in file ' + file))
.on('error', (err) => console.log('Error emitted: ' + err.message))
// 結果:
/**
* fileA.txt was read
* Matched "hello world" in file fileA.txt
* fileB.json was read
* Matched "hello NodeJS" in file fileB.json
* Matched "hello you" in file fileB.json
*/
EventEmitterクラスの拡張
const EventEmitter = require('events').EventEmitter
const fs = require('fs')
class FindPattern extends EventEmitter {
constructor(regex) {
super()
this.regex = regex
this.files = []
}
addFile(file) {
this.files.push(file)
return this
}
find() {
this.files.forEach(file => {
fs.readFile(file, 'utf8', (err, content) => {
if (err) {
return this.emit('error', err)
}
this.emit('fileread', file)
let match
if (match = content.match(this.regex)) {
match.forEach(elem => this.emit('found', file, elem))
}
})
})
return this
}
}
/* -------------------------------------------------------------------------- */
const findPatternObj = new FindPattern(/hello \\w+/)
findPatternObj
.addFile('./fileA.txt')
.addFile('./fileB.json')
.find()
.on('found', (file, match) => console.log(`Matched "${match}" in file ${file}`))
.on('error', err => console.log(`Error emitted ${err.message}`))
// 結果:
/**
* Matched "hello world" in file ./fileA.txt
* Matched "hello NodeJS" in file ./fileB.json
*/
emitメソッドは同期関数
const EventEmitter = require('events').EventEmitter
class SyncEmit extends EventEmitter {
constructor() {
super()
this.emit('ready')
}
}
/* -------------------------------------------------------------------------- */
const syncEmit = new SyncEmit()
syncEmit.on('ready', () => console.log(`
emitメソッドは同期関数なので、インスタンス生成時に即実行されます。「
そのため、インスタンス生成後にリスナーを登録しても、イベントが通知されることはありません。
`))
// 結果:
/**
*
*/
コールバックとの使い分け
const EventEmitter = require('events').EventEmitter
// EventEmitterによる実装
function helloByEvents() {
const eventEmitter = new EventEmitter()
setTimeout(() => eventEmitter.emit('hello', 'Hello World!'), 100)
return eventEmitter
}
// コールバックによる実装
function helloByCallback(callback) {
setTimeout(() => { callback('Hello World!') }, 100)
}
/* -------------------------------------------------------------------------- */
helloByEvents().on('hello', (message) => console.log(message))
helloByCallback((message) => console.log(message))
// 結果:
/**
* Hello World!
* Hello World!
*/
引数がコールバック、戻り値がEventEmitter