第一种方式,直接遍历循环:
这种方式最简单,要串联执行多个函数,可以遍历循环执行,代码如下:
// 1
let a1 = function (next) { console.log("a1"); }
let a2 = function (next) { console.log("a2"); }
let a3 = function (next) { console.log("a3"); }
let arr = [a1,a2,a3];
arr.forEach(e=>e());
第二种方式,按照洋葱结构来构造代码结构,类似如图:
如何构造这样的代码呢,代码示例如下:
let a1 = function (next) { console.log("a1"); next() }
let a2 = function (next) { console.log("a2"); next() }
let a3 = function (next) { console.log("a3"); next() }
let arr = [a1, a2, a3];
let a = arr.reduce(
(a, b) => { return () => b(a) },
() => console.log("start")
);
a();
观察源码,我们在定义函数时为函数增加一个参数next,next是当前执行函数执行完后,下一个执行函数。
通过reduce函数的处理后,我们得到了函数a,函数a的函数函数体,我们可以利用数学中的函数代入得到结果:
function a () {
console.log("a3");
( function (next) {
console.log("a2");
( function (next) {
console.log("a1");
( () => console.log("start") )()
} )()
} )()
}
上面的代码除了用reduce之外我们还可以使用循环来构造,代码如下:
let a1 = function (next) { console.log("a1"); next() }
let a2 = function (next) { console.log("a2"); next() }
let a3 = function (next) { console.log("a3"); next() }
let arr = [a1, a2, a3];
let a = () => console.log("start");
for (let i = 0; i < arr.length; i++) {
let next = a;
a = ()=>{ arr[i](next) }
} a();
a函数最终得到的结果和上面是一样的,只是方法不一样而已。
除了循环和reduce,我们还可以使用递归,代码如下:
let a1 = function (next) { console.log("a1"); next() }
let a2 = function (next) { console.log("a2"); next() }
let a3 = function (next) { console.log("a3"); next() }
let arr = [a1, a2, a3];
var i = 0;
function next() { var task = arr[i++]; // 取出函数数组里的下一个函数
if (!task) {
// 如果函数不存在,
return return;
}
task(next); // 否则,执行下一个函数
}
next();
递归调用原理也是类似构造一个回调函数,不过更趋向于流程化执行,更倾向于一边执行一边构造,而不是向上面两种方式,上面两种方式是先构造后执行。
阅读源码,我们定义了一个next函数和以一个全局变量i,i来标记执行到哪一个函数了,next调用标志着递归调用开始,每次执行i都会递增,然后从数组中取出中间件执行,中间件执行时传递进next,重复进行下一个调用轮回。
以上便是串联执行N(未知)个函数多种方式,应用最多的就是js技术栈中的中间件,redux的中间件,express的中间件都是用的以上的方法,多操作,多思考,微小改进每天进步一点点,希望对你有所帮助。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。