外星人源码论坛 首页 编程经验 JS-链式调用回调函数

JS-链式调用回调函数

2018-3-5 06:29
原作者: 外星人源码网 来自: 外星人源码网 收藏 分享 邀请

聊一下背景: 最近在开发项目的时候,因为需要数据同步处理,所以会遇到很多涉及到函数回调的地方。最多的达到了7个!不管是自己撸代码,还是维护代码,基本都是一项很烦心的事,特别要改原先其他同事写的逻辑, ...

聊一下背景:
最近在开发项目的时候,因为需要数据同步处理,所以会遇到很多涉及到函数回调的地方。最多的达到了7个!不管是自己撸代码,还是维护代码,基本都是一项很烦心的事,特别要改原先其他同事写的逻辑,我宁愿重新写。

代码都是这样的:

a(xx,function(){
    b(xx,function(){
        c(xx,function(){
        .....
        });
    });
});

又或者这样的:

    function a(xx){
    //.....
    b();
    }
    function b(xx){
    //.....
    c();
    }
    
    ......

故,抽了点时间写了一个:以链式调用的形式用来处理需要回调的函数。


源码:
/**
*链式回调
**/

function chainedFn(chain){
    // 入参数据校验 ...
    for(var i=0;i<chain.length;i++){
        if(!chain[i]["fnName"] || (typeof chain[i]["fnName"]) != "function"){
            console.log("error:参数有误!");
            return;
        }
    }
    
    // 如果只有一条,则直接调用 ...
    if(chain.length < 2){
        (new chain[0]["fnName"](chain[0]["fnArg"]||"")).fnCont();
        return;
    }
    
    // 组合链条 ...
    var firstFn = (function combinationFn(index){
        var curFnIndex = index || 0; //当前函数索引
        var curArg = chain[curFnIndex]["fnArg"] || ""; //当前函数参数
        var callBack = ""; //当前函数参数回调
        
        // 如果存在下一条,则将下一条绑定为当前的回调 ...
        if(curFnIndex + 1 <  chain.length){
            callBack  = combinationFn(curFnIndex + 1).fnCont;
        }
        
        var curFn = new chain[curFnIndex]["fnName"](curArg,callBack);    
        if(curFn){
            return curFn;
        }else{
            return false;
        }
        
    })();
    
    // 启动链条 ...
    if(typeof firstFn.fnCont == "function"){
        firstFn.fnCont();
    }
}


链条模板:

chainedFn([
    {"fnName":对象名A,"fnArg":实例化参数},
    {"fnName":对象名B,"fnArg":实例化参数},
    {"fnName":对象名C,"fnArg":实例化参数}
]);
   
说明:chainedFn的入参是JSON数组,【对象名】需存在,且符合“对象模版”;【实例化】参数可无;
   

对象模版:

function 对象名(实例化参数,callback){
    this.fnCont = function(tArg1,tArg2...){ //fnCont:函数主体(函数名不可变),tArg:被回调的入参(参数类型和进行回调的函数约定)
        // 函数功能代码 ...
        
        
        if(typeof callback == "function"){
            callback(tArg1,tArg2...);//回调的入参(参数类型和被回调的函数约定)
        }
    }
};
说明:【实例参数】可为空;【fnCont】为函数主体,函数名不可修改;【fnCont】等于前一个对象的【callback】即: 

【“对象B”的fnCont】->【对象A的callback】,【“对象C”的fnCont】->【对象B的callback】...




链式调用回调函数都做了什么?
1-依照入参中的先后顺序,动态组合了回调函数;
2-将当前的【callback】和下一个对象的【fnCont】进行映射绑定;

我可以用它做什么?
1-根据实际情况,轻松调整回调顺序,或者增加函数;
2-把【callback】当成下一个链条对象的【this.functino】的调用;
3-给其他开发者或代码维护者更清晰的业务逻辑;

函数示例:
假设现在有3个需要同步的函数:fnA(FnA),fnB(FnB),fbC(FnC);
fnA的功能:将入参乘上10,然后传给fnB,同时规定fnB的倒计时时间;
fnB的功能:进入倒计时,倒计时结束后,将入参乘上5,然后传给fnC;
fnC的功能:将参数打印出来;

// 将入参乘上10,然后传给fnB,同时规定fnB的倒计时时间(10s)...
function FnA(arg,callback){
    this.fnCont = function(tArg){
        console.log("from FnA:初始化入参值是 " + arg);
        var num = arg * 10 ;
        if(typeof callback == "function"){
            console.log("from FnA:执行回调函数");
            callback(num,10);
        }
    }
}

// 倒计时结束后,将入参乘上5,然后传给fnC ...
function FnB(arg,callback){
    this.fnCont = function(tArg,cDown){
        console.log("from FnB:入参的值是" + tArg);
        var num = tArg * 5;
        var countDown = cDown;
        console.log("from FnB:进入倒计时 -> "+countDown+"s");
        var tTout = setInterval(function(){
            console.log("from FnB:进入倒计时 -> " + --countDown + "s");
            if(countDown <= 0){
                console.log("from FnB:倒计数结束");
                countDown = -1;
                clearTimeout(tTout);

                if(typeof callback == "function"){
                    console.log("from FnB:执行回调函数");
                    callback(num);
                }
            }
        },1000);

    }
};

// 将参数打印出来 ...
function FnC(arg,callback){
    this.fnCont = function(tArg,awr){
        console.log("from FnC:入参的值是" + tArg);
        if(typeof callback == "function"){
            callback();
        }
    }
};


// 组合链式关系 ...
chainedFn([
       {"fnName":FnA,"fnArg":2}, //规定初始值,和倒计时时间
       {"fnName":FnB},//倒计时结束后,进行一些操作
       {"fnName":FnC,},//展示处理结果
       ]);
   

执行结果:

from FnA:入参的值是 2
userCenter.js?v=undefined:53 from FnA:执行回调函数
userCenter.js?v=undefined:60 from FnB:入参的值是20
userCenter.js?v=undefined:63 from FnB:进入倒计时 -> 10s
userCenter.js?v=undefined:65 from FnB:进入倒计时 -> 9s
userCenter.js?v=undefined:65 from FnB:进入倒计时 -> 8s
userCenter.js?v=undefined:65 from FnB:进入倒计时 -> 7s
userCenter.js?v=undefined:65 from FnB:进入倒计时 -> 6s
userCenter.js?v=undefined:65 from FnB:进入倒计时 -> 5s
userCenter.js?v=undefined:65 from FnB:进入倒计时 -> 4s
userCenter.js?v=undefined:65 from FnB:进入倒计时 -> 3s
userCenter.js?v=undefined:65 from FnB:进入倒计时 -> 2s
userCenter.js?v=undefined:65 from FnB:进入倒计时 -> 1s
userCenter.js?v=undefined:65 from FnB:进入倒计时 -> 0s
userCenter.js?v=undefined:67 from FnB:倒计数结束
userCenter.js?v=undefined:72 from FnB:执行回调函数
userCenter.js?v=undefined:82 from FnC:入参的值是100


鲜花

握手

雷人

路过

鸡蛋
该文章已有0人参与评论

请发表评论

全部评论

粉丝 阅读55 回复0
上一篇:
和其他库(jquery,backbone)一起使用react发布时间:2018-03-05
下一篇:
前端 排序算法总结发布时间:2018-03-05
推荐资讯
国内最专业的源码技术交流社区
全国免费热线电话

0373-5171417

周一至周日9:00-23:00

反馈建议

admin@eenot.com 在线QQ咨询

扫描二维码关注我们