Skip to content

Instantly share code, notes, and snippets.

@nariyu
Last active August 29, 2015 14:21
Show Gist options
  • Save nariyu/57a2b9408dd63865458f to your computer and use it in GitHub Desktop.
Save nariyu/57a2b9408dd63865458f to your computer and use it in GitHub Desktop.
EventEmitter (ES6)
'use strict';
// イベントリスナーの入れ物
let listenerMap = new Map;
/**
EventEmitter クラス
*/
export default class EventEmitter {
/**
コンストラクタ
*/
constructor() {
}
/**
イベント発射
@method trigger
@param {String} type 送信するイベントタイプ
*/
trigger() {
let args = Array.prototype.slice.call(arguments);
let type = args.shift();
let data;
if (typeof type === 'string') {
data = args.shift();
} else {
data = type;
type = type.type;
}
let namespace = '';
if (type.indexOf('.') > 0) {
[type, namespace] = type.split('.');
}
if (!data) data = {};
data.type = type;
let listeners = listenerMap.get(this);
if (!listeners) {
listeners = {}
listenerMap.set(this, listeners);
}
let callbacks = [];
for (let lType in listeners) {
let lCallback = listeners[lType];
if (namespace === '' && lType.indexOf('.') > 0)
[lType, ] = lType.split('.');
if (lType === type)
callbacks = callbacks.concat(lCallback);
}
for (let callback of callbacks)
callback.call(this, data);
}
emit() {
this.trigger.apply(this, Array.prototype.slice.call(arguments));
}
/**
イベントを待ち受ける
@method on
@param {String} type 受信を待ち受けたいイベントタイプ
@param {Function} callback 受信した時に実行したい処理
*/
on(type, callback, context) {
if (callback && context)
callback = callback.bind(context);
let listeners = listenerMap.get(this);
if (!listeners) {
listeners = {}
listenerMap.set(this, listeners);
}
if (!listeners[type])
listeners[type] = [];
listeners[type].push(callback);
}
addEventListener(type, callback) {
this.on(type, callback);
}
/**
イベント待ち受けを解除する
@method off
@param {String} type 受信を解除したいイベントタイプ
@param {Function} callback 受信を解除したい処理
*/
off(type, callback, context) {
if (callback && context)
callback = callback.bind(context);
let listeners = listenerMap.get(this);
if (!listeners) {
listeners = {}
listenerMap.set(this, listeners);
}
let namespace = '';
if (type.indexOf('.') > 0)
[type, namespace] = type.split('.');
if (!listeners.hasOwnProperty(type)) {
return
}
// callback がない場合は、type のすべてのリスナーを解除
if (!callback) {
if (namespace === '') {
for (let lType in listeners) {
let lCallback = listeners[lType];
let olType = lType;
if (lType.indexOf('.') > 0)
[lType, ] = lType.split('.');
if (lType === type)
delete listeners[olType];
}
} else {
delete listeners[type + '.' + namespace];
}
//
} else {
let i = 0;
let arr = listeners[type];
let len = arr.length;
while (i < len) {
let cb = arr[i];
if (cb == callback)
if (len === 1)
delete listeners[type];
else
arr.splice(i, 1);
break;
i++;
}
}
let keys = [];
for (let key in listeners) {
keys.push(key);
}
if (keys.length == 0) {
listenerMap.delete(this);
}
}
removeEventListener(type, callback) {
this.off(type, callback);
}
/**
すべてのイベントリスナーを削除する
@method removeAllListeners
*/
removeAllListeners() {
listenerMap.delete(this);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment