zoukankan      html  css  js  c++  java
  • 【nodejs原理&源码赏析(2)】KOA中间件的基本运作原理

    【摘要】 KOA中间件的基本运作原理

    pic0.jpg

    示例代码托管在: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.PNG

    六. 在服务器端运行

    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.PNG

    作者:大史不说话 

  • 相关阅读:
    git 错误 fatal: Not a valid object name: 'master'.
    SQL: select一组数据,concat同表同列的数据
    Linux curl usage
    Regular Expression
    浅谈Linux Process status,环境锁
    浅谈Manpage
    Java文件读写详解。 附txt乱码问题, html乱码问题
    在ubuntu 18.04下装有线守护wg
    centOS 7 换ssh端口
    如何把DEBIAN变成UBUNTU-DESKTOP最少化安装
  • 原文地址:https://www.cnblogs.com/2020-zhy-jzoj/p/13165589.html
Copyright © 2011-2022 走看看