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

    作者:大史不说话 

  • 相关阅读:
    【转】win8.1下安装ubuntu
    Codeforces 1025G Company Acquisitions (概率期望)
    Codeforces 997D Cycles in Product (点分治、DP计数)
    Codeforces 997E Good Subsegments (线段树)
    Codeforces 1188E Problem from Red Panda (计数)
    Codeforces 1284E New Year and Castle Building (计算几何)
    Codeforces 1322D Reality Show (DP)
    AtCoder AGC043C Giant Graph (图论、SG函数、FWT)
    Codeforces 1305F Kuroni and the Punishment (随机化)
    AtCoder AGC022E Median Replace (字符串、自动机、贪心、计数)
  • 原文地址:https://www.cnblogs.com/huaweicloud/p/11861566.html
Copyright © 2011-2022 走看看