KOA中間件的基本運做原理

示例代碼託管在:http://www.github.com/dashnowords/blogshtml

博客園地址:《大史住在大前端》原創博文目錄前端

華爲雲社區地址:【你要的前端打怪升級指南】node

在中間件系統的實現上,KOA中間件經過async/await來在不一樣中間件之間交換控制權,工做機制和結構很是類似,建議結合《express中間件系統的基本實現》對比學習,兩個框架所基於的語法特性有區別(express使用ES5的回調風格語法,KOA使用ES7的扁平式異步async/await風格語法),但在框架基本原理上是很相似的,只是中間件寫法和遍歷機制稍有不一樣。git

一. API層

  • 初始化方法github

    let middleware = new MiddleWare();
  • 添加中間件函數的方法web

    //Fn爲被添加的中間件,KOA中間件爲async函數
    middleware.use(Fn);
  • 預處理中間件棧express

    //將存儲於數組中的各個中間件組合爲按照「先進後出」原則執行的中間件系統。
    middleware.start = middleware.compose();
  • 啓動中間件隊列api

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

看一下效果(訪問服務器時自定義消息就能夠傳至前臺了):

相關文章
相關標籤/搜索