class app {
middleware = [];
// 装载中间件
use(middleware) {
this.middleware.push(middleware);
}
compose(callback) {
// 把 要被触发的上一层洋葱壳 作为下一层洋葱壳的next入参传入。
// reducer 的返回值,也就是下一层的next为 () => fn(next)。
const reducer = (next, fn) => () => fn(next);
// 第二个参数为洋葱的中心;可传入任意函数。(但必须传入函数)
this.middleware.reduceRight(reducer, callback)();
}
}
调用方法
const app = new app();
function middleware1(next) {
console.log('come in 1');
next();
console.log('come out 1');
}
function middleware2(next) {
console.log('come in 2');
next();
console.log('come out 2');
}
function middleware3(next) {
console.log('come in 3');
next();
console.log('come out 3');
}
app.use(middleware1);
app.use(middleware2);
app.use(middleware3);
app.compose(() => console.log('call controller'));
执行结果为
come in 1
come in 2
come in 3
call controller
come out 3
come out 2
come out 1
上述代码执行后 middleware为[middleware1, middleware2, middleware3];
reduceRight生成的函数为
() => middleware1(() => middleware2(() => middleware3(callback)))
compose被调用后
首先执行middleware1 打印 come in 1
然后执行至 middleware1的next
接下来就执行middleware2 middleware3
当执行至middleware3的next时,洋葱中心的callback被调用
所有next执行完毕
此时 middleware3 的 next() 之后的逻辑是 console.log('come out 3')
打印 come out 3 后,middleware3 执行完成
middleware3 执行完成则表示 middleware2 的 next() 执行完成
接下来执行middleware2 的 next() 后的逻辑
最后是 middleware1 的 next() 之后的逻辑。
整个过程就像 一只虫子进入一个洋葱之中,洋葱从外到里一层一层地打开, 离开之后洋葱又从里到外一层一层地关闭。