js原生是没有事件管理功能的,也看到了网上的一些比如js-signals或者EventEmitter等第三方库,但还是想自己写一套,同时支持同步和异步的。废话少说,上代码
下图为同步的事件处理
function HandlerBase(){
this._handlerDict = {};
}
Object.assign(HandlerBase.prototype, {
addHandler: function(type, callback, thisObj){
let list = this._handlerDict[type];
if(!list) {
list = [];
this._handlerDict[type] = list;
}
list.push({callback, thisObj});
},
removeHandler: function(type, callback, thisObj){
let list = this._handlerDict[type];
if(!list || list.length <= 0 ) return;
for(let i=0; i < list.length; ++i ) {
let obj = list[i];
if(obj.callback === callback && obj.thisObj === thisObj) {
list.splice(i, 1);
i--;
if(list.length <= 0 ) {
delete this._handlerDict[type];
break;
}
}
}
},
_dispatch: function(type, value){
let list = this._handlerDict[type];
if(!list || list.length <= 0 ) return;
list.forEach((item)=>{
item.callback.apply(item.thisObj, [value]);
});
},
});
接下来是异步的
/**
* 异步的事件处理机制
*/
function AsyncEventController(){
this._handlerDict = {};
this._dispatchList = [];
this._enabled = false;
this._init();
}
Object.assign(AsyncEventController.prototype, {
_init: function(){
},
addHandler: function(type, callback, thisObj){
let list = this._handlerDict[type];
if(!list) {
list = [];
this._handlerDict[type] = list;
}
list.push({callback, thisObj});
},
removeHandler: function(type, callback, thisObj){
let list = this._handlerDict[type];
if(!list || list.length <= 0 ) return;
for(let i=0; i < list.length; ++i ) {
let obj = list[i];
if(obj.callback === callback && obj.thisObj === thisObj) {
list.splice(i, 1);
i--;
if(list.length <= 0 ) {
delete this._handlerDict[type];
break;
}
}
}
},
_onEnterFrame: function(time){
while(this._dispatchList.length > 0 ) {
const {type, value} = this._dispatchList.pop();
this._doDispatch(type, value);
}
this._enabled = false;
},
_dispatch: function(type, value){
this._dispatchList.push({type, value});
if(!this._enabled){
requestAnimationFrame(this._onEnterFrame.bind(this));
this._enabled = true;
}
},
_doDispatch: function(type, value){
let list = this._handlerDict[type];
if(!list || list.length <= 0 ) return;
list.forEach((item)=>{
item.callback.apply(item.thisObj, [value]);
});
},
});