文档开发者中心
我的

nodejs原理and源码赏析(2)KOA中间件的基本运作原理

在中间件系统的实现上,KOA中间件通过async/await来在不同中间件之间交换控制权,工作机制和栈结构非常相似,建议结合《express中间件系统的基本实现》对比学习,两个框架所基于的语法特性有区别(express使用ES5的回调风格语法,KOA使用ES7的扁平式异步async/await风格语法),但在框架基本原理上是很类似的,只是中间件写法和遍历机制稍有不同。


一. API层


  • 初始化方法

    let middleware = new MiddleWare();
  • 添加中间件函数的方法

    //Fn为被添加的中间件,KOA中间件为async函数middleware.use(Fn);
  • 预处理中间件栈

    //将存储于数组中的各个中间件组合为按照“先进后出”原则执行的中间件系统。middleware.start = middleware.compose();
  • 启动中间件队列

    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);
            }
          }
       }
   }
}

三. 使用use方法添加中间件


//添加回调函数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);


看一下效果(访问服务器时自定义消息就可以传至前台了):


——————————————————

BY:HW-SWQ

点赞
4
收藏
4
回复
7
分享
举报
浏览1403 发布于2019-10-31 07:30未知归属地
全部评论
最多点赞
最新发布
最早发布

楼主要多发些这种内容的,你太有才了

8楼回复于2020-04-26 02:35 未知归属地

不禁感叹:厉害的干货

6楼回复于2020-04-22 02:33 未知归属地

这帖子还是值得讨论的

5楼回复于2020-04-20 02:14 未知归属地

是这样呀,我也学习了

4楼回复于2020-04-19 06:22 未知归属地

从前一个帖子来的,学习了

3楼回复于2019-10-31 08:38 未知归属地

关联阅读:nodejs原理and源码赏析(1)express中间件系统的基本实现

2楼回复于2019-10-31 07:32 未知归属地

nodejs原理and源码赏析第二篇来了~

1楼回复于2019-10-31 07:31 未知归属地
写回答
新增插入模板功能
一键使用模板,快速填写内容,轻松发帖~
知道了
  • 为了保障您的信息安全,请勿上传您的敏感个人信息(如您的密码等信息)和您的敏感资产信息(如关键源代码、签名私钥、调试安装包、业务日志等信息),且您需自行承担由此产生的信息泄露等安全风险。
  • 如您发布的内容为转载内容,请注明内容来源。

我要发帖子

目录 收起
一. API层
二. 核心类的定义
三. 使用use方法添加中间件
四. 中间件实例
五. 查看运行结果
六. 在服务器端运行
了解社区公约,与您携手共创和谐专业的开发者社区。