示例代码托管在:http://www.github.com/dashnowords/blogshtml
博客园地址:《大史住在大前端》原创博文目录前端
华为云社区地址:【你要的前端打怪升级指南】node
在中间件系统的实现上,KOA
中间件经过async/await
来在不一样中间件之间交换控制权,工做机制和栈结构很是类似,建议结合《express中间件系统的基本实现》对比学习,两个框架所基于的语法特性有区别(express
使用ES5
的回调风格语法,KOA
使用ES7
的扁平式异步async/await
风格语法),但在框架基本原理上是很相似的,只是中间件写法和遍历机制稍有不一样。git
初始化方法github
let middleware = new MiddleWare();
添加中间件函数的方法web
//Fn为被添加的中间件,KOA中间件为async函数 middleware.use(Fn);
预处理中间件栈express
//将存储于数组中的各个中间件组合为按照“先进后出”原则执行的中间件系统。 middleware.start = middleware.compose();
启动中间件队列api
middleware.start(ctx);
/* * KOA中间件框架的基本实现 */ class MiddleWare { constructor(){ this.queue = [] } //添加中间件函数 use(fn){ this.queue.push(fn); } //合并中间件处理流,是一个高阶函数,调用一次后会生成真正须要的函数。 compose(){ return function (ctx, next) { let _this= this; let index = -1; return dispatch(0); /** * KOA中间件的工做的步进函数 */ function dispatch(i) { index = i; //依次取用数组中添加的中间件函数 let fn = i === _this.queue.length ? next : _this.queue[i]; if(!fn){ return Promise.resolve(); } try{ /* *中间件函数的形式为 async fn(ctx, next),能够看到此处透传了ctx的引用, *同时next是一个延迟执行中间件队列中下一个中间件的函数,也就是说若是在前 *一个中间件的函数体中调用 await next(),就会启动下一个中间件,实际执行 *的函数是dispatch(i+1)。 */ return Promise.resolve(fn(ctx,()=>{ return dispatch(i+1); })); }catch(err){ return Promise.reject(err); } } } } }
//添加回调函数 middleware.use(async function(ctx, next){ console.log('step 001'); ctx.info = 'go through middleware1'; await next(); console.log('step 006'); }); middleware.use(async function(ctx, next){ console.log('step 002'); await next(); console.log('step 005'); }); middleware.use(async function(ctx, next){ console.log('step 003'); await next(); console.log('step 004'); });
//初始化 let middleware = new MiddleWare(); /* ...此处为添加中间件的代码 */ middleware.start = middleware.compose();
能够看到有错误发生和正常响应时的不一样结果:数组
用node
起一个web服务器那真是太随意了~服务器
//启动http服务 http.createServer(function(req, res){ console.log(req.url); let info = {}; middleware.start(info); res.end(JSON.stringify(info)); }).listen(9527);
看一下效果(访问服务器时自定义消息就能够传至前台了):