Authored by QC-L

更新 event 事件,添加单独监听方法

... ... @@ -181,8 +181,7 @@ class App extends Component {
loginedCallBack();
}
} else {
event.on('my-user-login-success', () => {
event.off('my-user-login-success');
event.one('my-user-login-success', () => {
if (loginSuccess) {
loginSuccess();
}
... ... @@ -206,8 +205,7 @@ class App extends Component {
loginedCallBack();
}
} else {
event.on('my-user-login-success', () => {
event.off('my-user-login-success');
event.one('my-user-login-success', () => {
if (loginSuccess) {
loginSuccess();
}
... ... @@ -223,8 +221,7 @@ class App extends Component {
loginedCallBack();
}
} else {
event.on('my-user-login-success', () => {
event.off('my-user-login-success');
event.one('my-user-login-success', () => {
if (loginSuccess) {
loginSuccess();
}
... ... @@ -242,8 +239,7 @@ class App extends Component {
loginedCallBack();
}
} else {
event.on('my-user-login-success', () => {
event.off('my-user-login-success');
event.one('my-user-login-success', () => {
if (loginSuccess) {
loginSuccess();
}
... ... @@ -254,8 +250,7 @@ class App extends Component {
}
});
} else {
event.on('my-user-login-success', () => {
event.off('my-user-login-success');
event.one('my-user-login-success', () => {
if (loginSuccess) {
loginSuccess();
}
... ...
export default {
listeners: [],
on(type, handle) {
// first remove and add
this.off(type, handle);
if (typeof handle === 'function') {
console.debug(`listen event ${type}`);
this.listeners.push([type, handle]);
}
},
off(type, handle) {
let index = -1;
if (typeof handle === 'function' &&
this.listeners.some(([itype, ihandle]) => {
index++;
return itype === type && handle.name && ihandle.name === handle.name;
})
) {
this.listeners.splice(index, 1);
}
},
emit(type, ...params) {
this.listeners.forEach(([listenType, handle]) => type === listenType && handle(...params));
console.debug(`receive event ${type}: ${JSON.stringify(params)}`);
},
removeAllListeners() {
this.listeners = [];
}
};
/**
* description: 参考借鉴 Node.js 的 EventEmitter
* 对象管理 event 事件
* @func on 监听
* @func emit 触发
* @func once 监听只执行一次
* @func remove 移除某个类型的某个事件
* @func removeAll 移除某个类型的全部事件/所有类型的全部事件
*/
class EventEmitter {
constructor() {
this._events = Object.create(null);
this._eventsCount = 0;
}
/**
* emit 触发事件
* @param type 事件名
* @param ...args 参数
*/
emit(type) {
let events, handler, len, isFn;
events = this._events;
handler = events[type];
if (!handler)
return false;
isFn = typeof handler === 'function';
len = arguments.length;
// 优化性能
switch(len) {
case 0:
throw new Error('"emit" not have arguments');
break;
case 1:
emitNone(handler, isFn, this);
break;
case 2:
emitOne(handler, isFn, this, arguments[1]);
break;
case 3:
emitTwo(handler, isFn, this, arguments[1], arguments[2]);
break;
case 4:
emitThree(handler, isFn, this, arguments[1], arguments[2], arguments[3]);
break;
default:
args = new Array(len - 1);
for (let i = 1; i < len; i++) {
args[i - 1] = arguments[i];
}
emitMany(handler, isFn, this, args);
}
return true;
}
one(type, listener,) {
let events;
if (typeof listener !== 'function')
throw new Error('"listener" argument must be a function');
events = this._events;
if (typeof events === 'undefined') {
events = this._events = Object.create(null);
this._eventsCount = 0;
}
events[type] = listener;
++this._eventsCount;
return this;
}
_addListener(type, listener, prepend) {
let events;
let existing;
if (typeof listener !== 'function')
throw new Error('"listener" argument must be a function');
events = this._events;
if (typeof events === 'undefined') {
events = this._events = Object.create(null);
this._eventsCount = 0;
} else {
existing = events[type];
}
if (!existing) {
existing = events[type] = listener;
++this._eventsCount;
} else {
if (typeof existing === 'function') {
existing = events[type] = prepend ? [listener, existing] : [existing, listener];
} else if (prepend) {
existing.unshift(listener);
} else {
existing.push(listener);
}
}
return this;
}
/**
* on 监听事件
* @param type 事件名
* @param listener 监听函数
*/
on(type, listener) {
return this._addListener(type, listener, false);
}
/**
* once 监听只执行一次事件
* @param type 事件名
* @param listener 只执行一次的监听函数
*/
once(type, listener) {
if (typeof listener !== 'function')
throw new Error('"listener" argument must be a function');
this.on(type, _onceWrap(this, type, listener));
return this;
}
/**
* prepend 优先监听事件
* @param type 事件名
* @param listener 要优先的监听函数
*/
prepend(type, listener) {
return this._addListener(type, listener, true);
}
/**
* prependOnce 优先只执行一次的监听事件
* @param type 事件名
* @param listener 要优先且只执行一次的监听函数
*/
prependOnce(type, listener) {
if (typeof listener !== 'function')
throw new TypeError('"listener" argument must be a function');
this.prepend(type, _onceWrap(this, type, listener));
return this;
}
/**
* remove 移除的监听事件
* @param type 事件名
* @param listener 要移除的监听函数(可选)
*/
remove(type, listener) {
let list, events, position, originalListener;
if (typeof listener !== 'function')
throw new TypeError('"listener" argument must be a function');
events = this._events;
if (!events) {
return this;
}
list = events[type];
if (!list) {
return this;
}
if (list === listener || list.listener === listener) {
if (--this._eventsCount === 0) {
this._events = Object.create(null);
} else {
delete events[type];
}
} else if (typeof list !== 'function') {
position = -1;
for (let i = list.length - 1; i >= 0; i--) {
if (list[i] === listener || list[i].listener === listener) {
originalListener = list[i].listener;
position = i;
break;
}
}
if (position < 0) {
return this;
}
if (position === 0) {
list.shift();
} else {
spliceOne(list, position);
}
if (list.length === 1) {
events[type] = list[0];
}
}
return this;
}
/**
* removeAll 移除某事件名的全部监听事件/移除全部事件名的事件
* @param type 事件名
*/
removeAll(type) {
let listeners, events;
events = this._events;
if (!events)
return this;
if (arguments.length === 0) {
var keys = Object.keys(events);
var key;
for (let i = 0; i < keys.length; ++i) {
key = keys[i];
this.removeAll(key);
}
this._events = Object.create(null);
this._eventsCount = 0;
return this;
}
listeners = events[type];
if (typeof listeners === 'function') {
this.remove(type, listeners);
} else if (listeners !== undefined) {
for (let i = listeners.length - 1; i >= 0; i--) {
this.remove(type, listeners[i]);
}
}
return this;
}
eventNames() {
return this._eventsCount > 0 ? Reflect.ownKeys(this._events) : [];
}
}
const emitNone = (handler, isFn, self) => {
if (isFn) {
handler.call(self);
} else {
let len = handler.length;
let listeners = arrayClone(handler, len);
for (let i = 0; i < len; ++i)
listeners[i].call(self);
}
}
const emitOne = (handler, isFn, self, arg1) => {
if (isFn) {
handler.call(self, arg1);
} else {
let len = handler.length;
let listeners = arrayClone(handler, len);
for (let i = 0; i < len; ++i)
listeners[i].call(self, arg1);
}
}
const emitTwo = (handler, isFn, self, arg1, arg2) => {
if (isFn) {
handler.call(self, arg1, arg2);
} else {
let len = handler.length;
let listeners = arrayClone(handler, len);
for (let i = 0; i < len; ++i)
listeners[i].call(self, arg1, arg2);
}
}
const emitThree = (handler, isFn, self, arg1, arg2, arg3) => {
if (isFn) {
handler.call(self, arg1, arg2, arg3);
} else {
let len = handler.length;
let listeners = arrayClone(handler, len);
for (let i = 0; i < len; ++i)
listeners[i].call(self, arg1, arg2, arg3);
}
}
const emitMany = (handler, isFn, self, args) => {
if (isFn) {
handler.apply(self, args);
} else {
let len = handler.length;
let listeners = arrayClone(handler, len);
for (let i = 0; i < len; ++i)
listeners[i].apply(self, args);
}
}
const spliceOne = (list, index) => {
for (; index + 1 < list.length; index++)
list[index] = list[index + 1];
list.pop();
}
function onceWrapper(...args) {
if (!this.fired) {
this.target.remove(this.type, this.wrapFn);
this.fired = true;
Reflect.apply(this.listener, this.target, args);
}
}
const _onceWrap = (target, type, listener) => {
var state = { fired: false, wrapFn: undefined, target, type, listener };
var wrapped = onceWrapper.bind(state);
wrapped.listener = listener;
state.wrapFn = wrapped;
return wrapped;
}
function arrayClone(arr, n) {
var copy = new Array(n);
for (var i = 0; i < n; ++i)
copy[i] = arr[i];
return copy;
}
const event = new EventEmitter();
export default event;
\ No newline at end of file
... ...