See the Pen Koa.js compose by Willard (@ifyour) on CodePen.
// Koa.js 核心代码 compose// 决定了 Koa.js 中间件的调用顺序,也就是洋葱模型function compose(middleware) {return function(context, next) {// 最后调用的 middleware 索引let index = -1;return dispatch(0);function dispatch(i) {if (i <= index)return Promise.reject(new Error("next() called multiple times"));index = i;let fn = middleware[i];if (i === middleware.length) fn = next;if (!fn) return Promise.resolve(); // 结束递归条件try {return Promise.resolve(fn(context, function next() {return dispatch(i + 1); // 递归调用自身}));} catch (err) {return Promise.reject(err);}}};}async function a (ctx, next) {console.log(1);const hello = await Promise.resolve('Hello, node.js');console.log(hello);await next();console.log('a end');}async function b (ctx, next) {console.log(2);const hello = await Promise.resolve('Hello, node.js');console.log(hello);await next();console.log('b end');}//// Demo:测试中间件调用//const myCtx = {};compose([a, b])(myCtx);
执行结果:
1"Hello, node.js"2"Hello, node.js""b end""a end"
