JS-異步函數鏈式調用2(精簡版,推薦)

基於《JS-異步函數鏈式調用》使用起來不是很方便直觀,對此作一次優化,更符合使用的精簡版:segmentfault

//源碼
function simpleChainedFn(){
    var localParam = arguments; //當前入參
    var firstFnArguments; //首節點的入參(數組格式)
    var chainLength = localParam.length; //除掉首節點入參,全部鏈條長度

    // 入參數據校驗...
    for(i=0;i<localParam.length;i++){
        if(!localParam[i] || typeof localParam[i] !== "function"){
            // 若是當前是卻是第二個,則認爲是首節點的入參;鏈條長度減1...
            if(i === localParam.length - 1){
                firstFnArguments = localParam[i];
                chainLength -= 1;
            }else{
                console.log("【error】鏈條參數有誤!");
                return;
            }

        }
    }

    // 組合鏈條...
    var firstFn = (function combinationFn(index){
        var curFnIndex = index || 0; //當前函數索引
        var callBack; //當前函數參數回調

        // 若是存在下一條,則將下一條綁定爲當前的回調...
        if(curFnIndex + 1 <  chainLength){
            callBack = arguments.callee(curFnIndex + 1);
        }

        var curFn = localParam[curFnIndex];
        if(curFn){
            if(callBack){
                curFn.callback = callBack;
            }
            return curFn;
        }else{
            return false;
        }

    })();

    // 啓動鏈條 ...
    if(typeof firstFn === "function"){
        var suctnParam = "";
        if(firstFnArguments){
            for(var i = 0 ; i < firstFnArguments.length; i ++)
            {
                suctnParam += "firstFnArguments[" + i + "]" + (i === firstFnArguments.length - 1 ? "" : ",");
            }
        }
        eval("firstFn(" + suctnParam + ")");

    }
}

// 獲取回調函數
function getCallbackFn(){
    return this.callback;
}

鏈條模板:數組

simpleChainedFn(函數1,函數2,....,函數n,[首節點入參1,首節點入參2,...首節點入參n]);

模板說明:
    一、支持多個函數自動擴展;
    二、若是最後一個參數是數組,則做爲首節點調用時的入參;
    三、首節點入參個數會隨着數組長度自動擴展;

函數模板:異步

function 函數名(入參1,入參2,...,入參n){
    var callback = getCallbackFn.call(arguments.callee);
    // TODO...
    

    if(callback && typeof callback === "function"){
        callback(入參1,入參2,...,入參n);
    }

}

模板說明:
    一、"var callback = getCallbackFn.call(arguments.callee);"儘可能在函數體前邊;

實際運用
假設如今有3個須要同步執行的函數:fnA,fnB,fnC;
fnA的功能:將基數(入參1),乘上乘積(入參2),結果值和倒計時(入參3)傳給fnB;
fnB的功能:進入倒計時,倒計時結束後,將入參乘上5,而後傳給fnC;
fnC的功能:將參數打印出來;函數

// 組合鏈式關係 ...
simpleChainedFn(fnA,fnB,fnC,[2,10,5]);




// 將基數(入參1),乘上乘積(入參2),結果值和倒計時(入參3)傳給fnB...
function fnA(base,multiplier,cDown){
    var callback = getCallbackFn.call(arguments.callee);

    console.log("【fnA】基數:" + base + ",乘積:" + multiplier + ",倒計時:" + cDown);
    var num = base * multiplier ;

    if(callback && typeof callback === "function"){
        console.log("【fnA】執行完畢,結果爲:" + num + ",準備進入fnB。");
        callback(num,cDown); // 等價於fnB
    }

}

// 進入倒計時,倒計時結束後,將入參乘上5,而後傳給fnC...
function fnB(base,cDown){
    var callback = getCallbackFn.call(arguments.callee);

    console.log("【fnB】基數:" + base + ",倒計時:" + cDown);
    var countDown = cDown;
    var tTout = setInterval(function(){
        console.log("【fnB】進入倒計時 -> " + --countDown + "s");
        if(countDown <= 0){
            console.log("【fnB】倒計數結束");
            countDown = -1;
            clearTimeout(tTout);

            var num = base * 5;

            if(callback && typeof callback === "function"){
                console.log("【fnB】執行完畢,結果爲:" + num + ",準備進入fnC。");
                callback(num);// 等價於fnC
            }
        }
    },1000);
}

// 將參數打印出來;
function fnC(tArg){
    var callback = getCallbackFn.call(arguments.callee);

    console.log("【fnC】計算結果爲:" + tArg);
    if(callback && typeof callback === "function"){
        callback();
    }

}

執行結果:優化

【FnA】基數:2,乘積:10,倒計時:5
【FnA】執行完畢,結果爲:20,準備進入fnB。
【fnB】基數:20,倒計時:5
【fnB】進入倒計時 -> 4s
【fnB】進入倒計時 -> 3s
【fnB】進入倒計時 -> 2s
【fnB】進入倒計時 -> 1s
【fnB】進入倒計時 -> 0s
【fnB】倒計數結束
【fnB】執行完畢,結果爲:100,準備進入fnC。
【fnC】計算結果爲:100
相關文章
相關標籤/搜索