这篇文章的劈头是如许一段代码
这段代码的作用很简朴,就是让一系列的动画,按递次实行。而如许一层一层嵌套进去的作用就是一个实行完了,实行下一个。
为了处置惩罚这个问题我就想到了是否是能够把这些事宜放到一个数组里,然后顺次实行呢?也就是说完成一个seq(tasks,finally)
函数
/**
* @param {function []} tasks - function array
* @param {function} cb - 实行完的回调
*/
function seq(tasks, cb) {
}
我的思绪是每次实行完一个function
以后再实行下一个函数,假如实行到末了一个函数就实行末了的cb
即
function seq(tasks, cb) {
(function runTask(i) {
var task = tasks[i];
task(function() {
i++;
if (i !== tasks.length) {
runTask(i);
} else {
cb();
}
});
})(0);
}
然则明显这么完成并不文雅(Zhuāng Bī),那末有无更文雅的计划呢?明显是有的。我们能够运用ES5
的reduceRight
函数(MSDN文档)
假如你并不知道这个函数的话,我们就要从和它差不多的reduce
函数(MSDN文档)说起了。reduce
函数吸收两个参数callback
、initialValue
callback
实行数组中每一个值的函数,包括四个参数previousValue
上一次挪用回调返回的值,或者是供应的初始值(initialValue)currentValue
数组中当前被处置惩罚的元素index
当前元素在数组中的索引array
挪用 reduce 的数组
initialValue
作为第一次挪用 callback 的第一个参数。
/**
@examples
**/
var array = [
{
id: 1,
name: "小李"
}, {
id: 2,
name: "小张"
}, {
id: 3,
name: "小刘"
}, {
id: 4,
name: "小王"
}
]
var objMap = array.reduce(function(map,nowObj,index,array) {
map[nowObj.id] = nowObj;
return map;
},{});
很简朴的就把一个array,转成了一个以id
为key
,obj
为value
的ObjMap
有木有?就是这么简朴。reduceRight
函数的参数和reduce
函数一样,只不过是实行的递次与reduce
函数相反,是倒过来实行的。如许的话我们就能够把上面谁人tasks转换成相似最一开始那张图一样的构造。
function seq2(tasks, cb) {
tasks.reduceRight(function(cb, task) {
return function() {
return task(cb);
};
}, cb)();
}
//这段代码的推导以下
//第一次实行
function() {
return task5(cb);
};
//第二次实行
function() {
return task4(function() {
return task5(cb);
});
}
//第三次实行
function() {
return task3(function() {
return task4(function() {
return task5(cb);
});
});
};
//第四次实行
function() {
return task2(function() {
return task3(function() {
return task4(function() {
return task5(cb);
});
});
})
};
//末了一次实行
function() {
return task1(function() {
return task2(function() {
return task3(function() {
return task4(function() {
return task5(cb);
});
});
});
});
};
如许就得到了一个跟上面最一开始那张图如出一辙的一个function,然后最主要的是reduceRight
面谁人()
,他就是启动这个终究返回function的开关。
测试用例以下:
var tasks = [1, 2, 3, 4, 5];
tasks = tasks.map(function(i) {
return function(cb) {
setTimeout(function() {
console.log(i);
cb();
}, Math.random() * 500 | 0);
}
});
seq(tasks, function() {
console.log('all Done');
});
seq2(tasks, function() {
console.log('all Done');
});
这个问题是我公司的一名同事(先生)给我出的问题。第二个计划,也是他给我的思绪。谢谢我的这位先生,虽然在工作中我说的不多,然则在我内心里,我对您的崇敬那是简直了。哈哈。末了是github源代码