SyncCallback
先看用法
- 首先注册你的方法是通过拦截改写的
SyncCallback.register(this,__test.main,'main');return;
- 调用的方法名必须带有 callback_ 标识
var callresult= this.callback_();
- await: endawait; 组合声明
await:
var callresult= this.callback_();
//code
endawait;
下面是简单的示例
var __test = {
callback_test1 : function(callback){
var result = ' callback_test1 result value';
setTimeout(function(){
callback(result);
},10000);
},
callback_test2 : function(p1,callback){
var result = ' callback_test1 result value';
setTimeout(function(){
callback(result);
},10000);
},
main : function(){
//register
SyncCallback.register(this,__test.main,'main');return;
//test
await:
var value = this.callback_test1();
var localvalue = "localvalue";
await:
var value2 = this.callback_test2(value);
console.log(" test callback1 ===================", value);
console.log(" test callback2 ===================", value2);
console.log(" test callback3 localvalue ===================", localvalue);
endawait;
await:
var value2 = this.callback_test2(value);
console.log(" test callback2 ===================", value2);
endawait;
endawait;
}
}
//static test
__test.main();
__test.main();
//动态类 test
function testsync(){
this.abc = "xxx";
}
testsync.prototype.test = function(v){
//register
SyncCallback.register(this,this.test,'test');return;
//test
await:
var value = __test.callback_test1();
var localvalue = "localvalue";
await:
var value2 = __test.callback_test2(value);
console.log(" test callback3 localvalue ===================", localvalue);
endawait;
await:
var value2 = __test.callback_test2(value);
console.log(" test callback2 ===================", value2);
endawait;
endawait;
};
new testsync().test("v");
下面是介绍整个写作过程
fn1(function(){
fn2(function(){
fn3(function(){
fn4();
.....
});
});
});
写过JS的人都知道上面的代码是多头痛,第二次看肯定有想死的感觉 假如代码变成这样
var v1= callback_fn1();
var v2= callback_fn2(v1);
var v3= callback_fn3(v2);
//以上是程序未运行时的代码
//通过拦截进行改写
//第一次改写
var v1= callback_fn1(function(v1){
var v2= callback_fn2(v1);
var v3= callback_fn3(v2);
});
//第二次改写
var v1= callback_fn1(function(v1){
var v2= callback_fn2(function(v2){
var v3= callback_fn3(v2);
});
});
//第三次改写 最终代码变成这样
var v1= callback_fn1(function(v1){
var v2= callback_fn2(function(v2){
var v3= callback_fn3(function(v3){
});
});
});
以上是写代码的想法过程,或者说是原理 第一版本有个缺点,就是不知道什么情况下结尾 }) 所有直接在代码后面按次数补上
var _injection_end ="})";
while(i>0){
i--;
codestring += _injection_end;
}
直接昨天学习 b语言的时候,发现 start end; 声明 今早起来突然觉得这个可以用上,就变成
var _injection_end ="})";
codestring = codestring.replace(/await\s*\:/mg,'');
codestring = codestring.replace(/endawait\s*;/mg,_injection_end);
目前不支持
if(this.callback())
如果有这种逻辑,请写成
var value = this.callback();
if(value){
}
缺点
- 要先注册才能使用
- 调用的方法名要声明 callback_ 为什么这看下具体实现,希望谁有好的方法,或者正则强大的话,改写一下
核心文件
/**
* [@author](/user/author) solq
* [@deprecated](/user/deprecated) blog: cnblogs.com/solq
* */
//www.springnodejs.com
var STRIP_COMMENTS = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg;
var SyncCallback = {
/**
* [@param](/user/param) callObj 注册对象
* [@param](/user/param) fn 注册方法
* [@param](/user/param) fnName 注册名
* */
//public
register : function(callObj,fn,fnName){
if(typeof fn != 'function'){
return;
}
if( fnName==''){
return;
}
var key ='__overrideFunction_' + fnName;
if(callObj[key]!=null){
var params = this.getParamNames(callObj[key]);
callObj[key].apply(callObj,params);
//console.log("double run");
return;
}
this._aop(key,fn,callObj);
},
scanMarker : 'callback_', //简单的判断扫描方式
/**
* aop 拦截
* [@param](/user/param) container 注册对象
* [@param](/user/param) fn 注册方法
* [@param](/user/param) fnName 注册名
* */
//private
_aop : function(fnName,fn,container){
//scan code
//injection code
//overrideFunction
var codestring = this._scanCode(fn);
if(codestring.indexOf( this.scanMarker) <0 ){
return;
}
//console.log("first run");
var new_codestring = this._injectionCode(codestring);
var params = this.getParamNames(fn);
var newFuntion = this._overrideFunction(new_codestring,params);
container[fnName]=newFuntion;
container[fnName].apply(container,params);
},
/**
* 获得方法参数
* */
getParamNames : function(func) {
var fnStr = func.toString().replace(STRIP_COMMENTS, '')
var result = fnStr.slice(fnStr.indexOf('(')+1, fnStr.indexOf(')')).match(/([^\s,]+)/g)
if(result === null)
result = []
return result
},
/**
* 扫描方法 code
* */
_scanCode : function(fn){
var code=fn.toString().replace(STRIP_COMMENTS, '');
return code.substring(code.indexOf('{')+1, code.lastIndexOf('}'));
},
/**
* 注入增强代码
* */
_injectionCode : function(codestring){
var _injection_start ="var __$this = this;";
var _injection_end ="})";
//var i = 0 ;
codestring = codestring.replace(/var\s+(.*)\=.*callback_[^\)]+(.*)/mg,function(a,b,c,d){
//debug("codestring replace ==============",a," b====== ",b," c=============== ",c, " d============== ",d);
//i++;
var _injection_code ="function("+b+"){";
var result =a.replace(/\((.*)\)/,function(pa,pb){
var r ;
if(pb.trim()==''){
r = "("+_injection_code;
}else{
r = "("+pb+","+_injection_code;
}
return r;
});
//debug("result ====================",result);
return result;
});
//第一版本替换
/*
while(i>0){
i--;
codestring += _injection_end;
}*/
//第二版本替换
codestring = codestring.replace(/await\s*\:/mg,'');
codestring = codestring.replace(/endawait\s*;/mg,_injection_end);
//replace this
codestring = codestring.replace(/this\s*\./mg,'__$this.');
codestring = _injection_start + codestring;
codestring = codestring.replace(/SyncCallback\.register\(.*\);\s*return/mg,'');
//console.log("new code ==============",codestring);
return codestring;
},
/**
* 重写方法
* */
_overrideFunction : function(new_codestring,params){
if(params.length==0){
return new Function(new_codestring);
}
return new Function(params,new_codestring);
},
};