Created
August 30, 2017 23:24
-
-
Save uchcode/79b0e3a9b7611a6378ffb0ea57cc60e1 to your computer and use it in GitHub Desktop.
nodejs eventemitter example
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class StdioEmitter { | |
constructor(encoding='utf8') { | |
this.EVENT = { | |
DEFAULT : Symbol(), | |
ALL : Symbol(), | |
} | |
this.encoding = encoding | |
this.emitter = new (require('events').EventEmitter)() | |
this._event_all_listener = undefined | |
this._regexp_listener_dictionary = {} | |
this._base_listener = (data) => { | |
if (Object.prototype.toString.call(data).slice(8,-1).toLowerCase() != 'string') { | |
return | |
} | |
try { | |
let d = JSON.parse(data.trim()) | |
if (!this.emitter.emit(d.eventName, d.data)) { | |
this.emitter.emit(this.EVENT.DEFAULT, d.data) | |
} | |
} catch(e) { | |
let d = data.replace(/\n$/,'') | |
if (!this.emitter.emit(d, data)) { | |
this.emitter.emit(this.EVENT.DEFAULT, data) | |
} | |
} | |
} | |
process.stdin.on('data', this._base_listener) | |
} | |
on(eventName, listener) { | |
switch(eventName) { | |
case this.EVENT.ALL: | |
if (this._event_all_listener) { | |
throw new Error(`on(): already regist. EVENT.ALL.`) | |
} | |
process.stdin.on('data', listener) | |
this._event_all_listener = listener | |
break | |
default: | |
let type = Object.prototype.toString.call(eventName).slice(8,-1).toLowerCase() | |
if (type == 'regexp') { | |
if (this._regexp_listener_dictionary[eventName]) { | |
throw new Error(`on(): already regist. RegExp: ${eventName}`) | |
} | |
process.stdin.on('data', listener) | |
this._regexp_listener_dictionary[eventName] = listener | |
} else { | |
this.emitter.on(eventName, listener) | |
} | |
break | |
} | |
} | |
off(eventName, listener) { | |
switch(eventName) { | |
case this.EVENT.ALL: | |
if (this._event_all_listener) { | |
process.stdin.removeListener('data', this._event_all_listener) | |
this._event_all_listener = undefined | |
} | |
break | |
default: | |
let type = Object.prototype.toString.call(eventName).slice(8,-1).toLowerCase() | |
if (type == 'regexp') { | |
process.stdin.removeListener('data', listener) | |
if (this._regexp_listener_dictionary[eventName] == listener) { | |
delete this._regexp_listener_dictionary[eventName] | |
} | |
} else { | |
this.emitter.removeListener(eventName, listener) | |
} | |
break | |
} | |
} | |
offAll(eventName) { | |
switch(eventName) { | |
case this.EVENT.ALL: | |
if (this._event_all_listener) { | |
process.stdin.removeListener('data', this._event_all_listener) | |
this._event_all_listener = undefined | |
} | |
break | |
default: | |
let type = Object.prototype.toString.call(eventName).slice(8,-1).toLowerCase() | |
if (type == 'regexp') { | |
let listener = this._regexp_listener_dictionary[eventName] | |
if (listener) { | |
process.stdin.removeListener('data', listener) | |
delete this._regexp_listener_dictionary[eventName] | |
} | |
} else { | |
this.emitter.removeAllListeners(eventName) | |
} | |
break | |
} | |
} | |
removeListener(eventName, listener) { | |
this.off(eventName, listener) | |
} | |
removeAllListeners(eventName) { | |
this.offAll(eventName) | |
} | |
once(eventName, listener) { | |
this.emitter.once(eventName, listener) | |
} | |
emit(data, argument='') { | |
switch(data) { | |
case this.EVENT.DEFAULT: | |
this.emitter.emit(this.EVENT.DEFAULT, argument) | |
break | |
default: | |
process.stdin.emit('data', data) | |
break | |
} | |
} | |
regexp(eventName, listener) { | |
return [eventName, (data) => { | |
try { | |
let d = data.replace(/\n$/,'') | |
if ( eventName.test(d) ) { | |
listener(data) | |
} | |
} catch(e) { | |
//console.log(e) | |
} | |
}] | |
} | |
set encoding(e) { | |
process.stdin.setEncoding(e) | |
process.stdout.setEncoding(e) | |
process.stderr.setEncoding(e) | |
} | |
get encoding() { | |
return process.stdin._readableState.encoding | |
} | |
} | |
/////////////////////////////////////////// | |
function output(data, terminator='\n') { | |
process.stdout.write(data + terminator) | |
} | |
function error(data, terminator='\n') { | |
process.stderr.write(data + terminator) | |
} | |
answer = Math.floor( Math.random() * (100) ) | |
rule = new StdioEmitter() | |
EVENT = rule.EVENT | |
rule.on(answer.toString(), () => { | |
output(`正解!! ${answer}`) | |
process.exit(0) | |
}) | |
rule.on('', () => { | |
error('ゲームを中止しました。') | |
error(`答えは ${answer} でした。`) | |
process.exit(1) | |
}) | |
rule.once('hint', () => { | |
if (answer > 50) { | |
output('答えは50より大きいです') | |
} else { | |
output('答えは50以下です') | |
} | |
}) | |
rule.on(...rule.regexp( /[^0-9]+/, (data) => { | |
if (data.trim() == 'hint') { | |
output('hintは一回だけ!') | |
} else { | |
error('半角数字の正数でお願いします') | |
} | |
})) | |
rule.on(EVENT.DEFAULT, (data) => { | |
let d = data.trim() | |
if (d > 100 || d <= 0) { | |
output(`答えは 1 〜 100 の間で!`) | |
} else if (d > answer) { | |
output(`${d}は大きい`) | |
} else if (d < answer) { | |
output(`${d}は小さい`) | |
} | |
}) | |
rule.on(EVENT.ALL, (data) => { | |
output('答え:', '') | |
}) | |
output('数当てゲーム!!') | |
output('1 〜 100 の間の整数を当ててください') | |
rule.emit(EVENT.ALL) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment