共计 2691 个字符,预计需要花费 7 分钟才能阅读完成。
基于《JS- 异步函数链式调用》使用起来不是很方便直观,对此做一次优化,更符合使用的精简版:
// 源码
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]);
模板说明:
1、支持多个函数自动扩展;
2、如果最后一个参数是数组,则作为首节点调用时的入参;
3、首节点入参个数会随着数组长度自动扩展;
函数模板:
function 函数名({入参}){
var callback = getCallbackFn.call(arguments.callee);
// TODO…
if(callback && typeof callback === “function”){
callback({入参});
}
}
模板说明:
1、为了避免闭包,”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