SyncCallback 同步方式书写异步代码
发布于 1年前 作者 solqkwgkwg 714 次浏览

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);
 },
}; 
4 回复

打包成 module吧 。 这个和async 区别大?

以人性的角度去做这件事 目的是为了更容易写代码同更容易看懂代码

又来一个这样的框架,好多

回到顶部