作者:gauseen原文:https://github.com/gauseen/blogKoa.jsKoa.js是一个极其精简的web服务框架,主要提供以下功能:HTTP服务:主要handles请求和响应中间件数据处理机制(洋葱模型)什么是AOP?AOP是AspectOrientedProgramming的缩写,中文意思是:面向方面的编程,是函数式编程的衍生范式。举个栗子:如果我想把一个苹果(源数据)加工成结果盘(最终数据),怎么办?做?①苹果(源数据)---->②洗苹果---->③切苹果---->④装盘---->⑤果盘(最终数据)有5个步骤,如果我想要升级果盘,我打算先把苹果削皮再切,放到盘子里排成五角星形,那么我的步骤应该是:①苹果(源数据)---->②苹果洗净---->③去皮去皮---->④苹果切块---->⑤装盘---->⑥摆成五角星形---->⑦果盘的以上步骤(最终数据)可视为对应的方法,步骤③和⑥加不加不影响果盘的制作结果。可见这是非常灵活的。其实这就是生活中面向切面编程的一个例子。也就是说,在已有的程序中,在不影响原有代码功能的情况下,增加或减少一些功能。什么是Koa.js洋葱模型?洋葱模型其实就是中间件处理的过程。中间件的生命周期大致是这样的:前处理交给其他中间件处理,后处理由多个中间件处理,形成所谓的洋葱模型,也就是AOP面向切面编程。一个应用程序。结合上面的果盘例子,在Koa.js中,apple(源数据)是request数据request,果盘(finaldata)是response数据response,中间处理过程就是Koa2.js的过程中间件功能处理。一个经典的切片洋葱图如下:先回顾一下,Koa2.js中以下代码的输出顺序是:constKoa=require('koa')constapp=newKoa()app.use(async(cxt,next)=>{console.log('middleware_01start')awaitnext()console.log('middleware_01end')})app.use(async(cxt,next)=>{console.log('middleware_02start')awaitnext()console.log('middleware_02end')})app.use(async(cxt,next)=>{console.log('middleware_03start')console.log('middleware_03end')})app.listen(3000)//浏览器访问:http://localhost:3000//输出序列为:middleware_01startmiddleware_02startmiddleware_03startmiddleware_03endmiddleware_02endmiddleware_01end如何实现洋葱模型(中间件机制)想一想,你怎么能实现Koa.js中间件处理机制呢?最简单的版本,代码如下://函数处理的数据letcontext={}functionmiddleware_01(cxt){console.log('middleware_01start')middleware_02(cxt)console.log('middleware_01end')}functionmiddleware_02(cxt){console.log('middleware_02开始')middleware_03(cxt)console.log('middleware_02end')}functionmiddleware_03(cxt){console.log('middleware_03start')console.log('middleware_03end')}//调用中间件compose函数functioncompose(){//默认调用第一个中间件middleware_01(context)}compose()//输出结果如下,和上面的中间件一致:middleware_01startmiddleware_02startmiddleware_03startmiddleware_03endmiddleware_02endmiddleware_01end上面的代码虽然实现了,但是也有不足之处,如:要显示要调用的函数名,不够灵活。升级版:constApp=function(){//中间件公共处理数据letcontext={}//中间件队列letmiddlewares=[]return{//putmiddleware将项目放入队列use(fn){middlewares.push(fn)},//调用中间件callback(){//初始调用中间件队列中的第一个中间件returndispatch(0)functiondispatch(i){//获取要执行的中间件函数letfn=middlewares[i]//执行中间件函数,回调参数为:公共数据,调用下一个中间件函数//返回一个Promise实例returnPromise.resolve(fn(context,functionnext(){dispatch(i+1)}))}},}}以上代码在没有考虑特殊边界条件的情况下完成了Koa2.js简单版对中间件的封装,我们测试一下//测试代码letapp=App()app.use(async(cxt,next)=>{console.log('middleware_01start')awaitnext()console.log('middleware_01end')})app.use(async(cxt,next)=>{console.log('middleware_02start')awaitnext()console.log('middleware_02end')})app.use(async(cxt,next)=>{console.log('middleware_03start')console.log('middleware_03end')})//在Koa2.js源码中,在http.createServer(callback)中调用callback//这里我们直接调用app.callback()//输出如下:middleware_01startmiddleware_02startmiddleware_03startmiddleware_03endmiddleware_02endmiddleware_01end如果想了解更多关于Koa2.js洋葱模型的信息,可以看这里的源码。.jsDesignPatterns-学习笔记什么是Aspect-OrientedProgrammingAOP?
