koa中间件实现分析

最近团队内部做了一个web app,用koa做服务端,一直对他中间件实现很感兴趣,对他的源码研究之后,写了一份简化版本的中间件实现。代码除了用到ES6的Generator和Promise,没有用到其他三方库,总共不到一百行,希望能帮助大家理解!

'use strict';
var middleware = [];

//向数据库请求数据
var getDataPromise = new Promise(function(resolve,reject){
   setTimeout(function(){
      resolve({
         data:'这就是数据'
      });
   },1500)
});

/**
 * session中间件
  * @param next
 */
function* session(next){
   console.log(1);
   yield next;
   console.log(2);
}
middleware.push(session);


/**
 * logger中间件
 */

function* logger(next){
   console.log(3);
   yield next;
   console.log(4);
}
middleware.push(logger);

/**
 * response中间件
 */
function* response(){
   console.log(5);
   console.log('请求数据库数据...');
   let data = yield getDataPromise;
   console.log(data);
   console.log(6);
}
middleware.push(response);


/**
 * 将中间件的遍历器函数转化为遍历器对象,并且将每一个遍历器对象指定为下一个遍历器对象的参数
 * @param next
 * @returns {*}
 */
function* toGeneratorObject(next){
   if (!next) next = function*(){};

   var i = middleware.length;

   while (i--) {
      next = middleware[i].call(this, next);
   }

   return yield *next;
}

//第一个中间件的遍历器对象
var firstMiddleWareGenerator = toGeneratorObject();

/**
 * 将中间件的遍历器对象包装成一个Promise
 * @param gen
 * @returns {Promise}
 */
function  wrapPromise(gen){
  return new Promise(function(resolve,reject){
     function onFullField (res){
        var ret = gen.next(res);
        next(ret);
     }
     onFullField();
     function next(ret){
        var value = null;
        if(ret.done){
           resolve(ret.value);
           return;
        }
        //假如是promise,不做任何处理
        if(typeof ret.value.then == 'function'){
           value = ret.value;
        }else { //假如不是,就包装成promise实例
           value = wrapPromise(ret.value);
        }
        value.then(onFullField);
     }
   });
}
wrapPromise(firstMiddleWareGenerator).then(function(){
   console.log('执行完了');
});

 

posted @ 2016-05-19 17:34  静水渊  阅读(1102)  评论(0编辑  收藏  举报