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

举报
大史不说话 发表于 2019/02/20 15:36:44 2019/02/20
【摘要】 KOA中间件的基本运作原理

pic0.jpgspacer.gif

示例代码托管在:http://www.github.com/dashnowords/blogs

博客园地址:《大史住在大前端》原创博文目录

华为云社区地址:【你要的前端打怪升级指南】

在中间件系统的实现上,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();

五. 查看运行结果

可以看到有错误发生和正常响应时的不同结果:

pic1.PNGspacer.gif

六. 在服务器端运行

node起一个web服务器那真是太随意了~

//启动http服务
http.createServer(function(req, res){
   console.log(req.url);
   let info = {};
   middleware.start(info);
   res.end(JSON.stringify(info));
}).listen(9527);

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

pic2.PNGspacer.gif



【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。