最近团队内部做了一个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 静水渊 阅读(1105) 评论(0) 推荐(0) 编辑
摘要: 由于项目需要,要计算出透视模式摄像机的四条外边。简直就是做数学题啊,尼玛,不过还好,最终是写出来了!using UnityEngine;using System.Collections;public class ClassA : MonoBehaviour{ public float dist... 阅读全文
posted @ 2015-06-02 14:25 静水渊 阅读(264) 评论(0) 推荐(0) 编辑
摘要: 1、U3D中的向量全部是结构类型,而结构类型属于值类型。所有假如把一个Transform对象的position、rotation、scale赋值给一个变量,相当于创建了一个值的新副本,不会影响该Transform对象的Transform对象的position、rotation、scale待续。。。 阅读全文
posted @ 2014-08-22 18:15 静水渊 阅读(113) 评论(0) 推荐(0) 编辑
摘要: 如果想使用StopCoroutine终止协同程序,那么StartCoroutine必须使用字符串传入方法的名字,其他方式无效! 阅读全文
posted @ 2014-08-18 17:28 静水渊 阅读(146) 评论(0) 推荐(0) 编辑
摘要: NGUI的2d UI的摄像机采用的是Orthographic正交视图其中有个size属性,它是指视图中心点到视图顶部的距离,默认是1个单位也就是Unity中的一米(Unity中的单位默认是米)。那么整个视图的高度是2个单位的高度;但是NGUI的大小尺寸的肯定不能这么小,熟悉ngui的人都知道,它的U... 阅读全文
posted @ 2014-08-08 15:20 静水渊 阅读(1472) 评论(0) 推荐(0) 编辑
摘要: UI2DSprite roleSprite=GetComponent("roleSprite");var roleSprites = Resources.LoadAll("sprite的路径");roleSprite.sprite2D = roleSprites[1];//1是某一帧的索引 阅读全文
posted @ 2014-07-29 17:54 静水渊 阅读(2119) 评论(0) 推荐(0) 编辑
摘要: 先贴代码See the Pen egpDo by 刘志刚 (@liuzhigang) on CodePen.DEMO中需要了解的模块:HTML中id是stage的div是游戏总容器,JS中的setViewport函数作用是设置视口宽高;css样式主要是为了让stage元素在手机浏览器中竖直和水平居中... 阅读全文
posted @ 2014-07-27 15:42 静水渊 阅读(9114) 评论(0) 推荐(0) 编辑
摘要: 电话面试,被问到行内元素和块级元素的区别。我回答说,块级元素独占一行,可设置宽高。行内元素不会独占一行,且不能设置宽高。然后面试官问我,img和input是行内元素么,他们能设置宽高吗?我一想,是啊,这两个也是行内元素,不过却能设置宽高啊。于是当场被问住了,说不出所以然。。。然后自己查阅资料,发现了... 阅读全文
posted @ 2014-07-25 13:25 静水渊 阅读(9241) 评论(0) 推荐(0) 编辑
摘要: 如果background-attachment值是fixed,则背景图片的位置相对于页面视口而言。比如background-position的值如果是center,则图片位于视口正中,而与所在元素的大小和位置无关。 阅读全文
posted @ 2014-07-18 12:37 静水渊 阅读(90) 评论(0) 推荐(0) 编辑
摘要: 容器的宽度是由内部的元素决定的。内部元素的外边据又是由容器的宽度决定的。这样不是构成死循环了吗?后来研究发现,浏览器的计算逻辑应该是这样的:浏览器先计算子元素在外边据为0的情况下,父元素的宽度。然后再根据百分比计算子元素的外边距,然后将子元素的宽度减去外边距。如果错误,恳请指正,谢谢! 阅读全文
posted @ 2014-04-02 12:00 静水渊 阅读(1180) 评论(0) 推荐(0) 编辑
点击右上角即可分享
微信分享提示