var server = handle;
server.route = path;
handle = function (req, res, next) { // req, res, next 中间件
server.handle(req, res, next);
};
}
// wrap vanilla http.Servers
if (handle instanceof http.Server) {
handle = handle.listeners( 'request' )[0]; // (req, res) // 最后的函数
}
// strip trailing slash
if (path[path.length - 1] === '/' ) {
path = path.slice(0, -1);
}
// add the middleware
debug( 'use %s %s' , path || '/' , handle.name || 'anonymous' );
this .stack.push({ route: path, handle: handle });
return this ;
};
从代码中,可以看出,use 方法添加中间件到 this.stack 中,其中 fn 中间件的形式有两种: function (req, res, next) 和 handle.handle(req, res, next) 这两种都可以。还有对 fn 情况进行特殊处理。
总的处理流程就是这样,用 use 方法添加中间件,用 next 编历中间件,用 finalHandle 进行最后的处理工作。
在代码中还有一个函数非常奇怪:
/* istanbul ignore next */ var defer = typeof setImmediate === 'function'
? setImmediate
: function (fn){ process.nextTick(fn.bind.apply(fn, arguments)) }
defer 函数中的 fn.bind.apply(fn, arguments) ,这个方法主要解决了,一个问题,不定参的情况下,第一个参数函数,怎样拿到的问题,为什么这样说呢?如果中我们要达到以上的效果,需要多多少行代码?
function () { var cb = Array.from(arguments)[0];
var args = Array.from(arguments).splice(1);
process.nextTick( function () {
cb.apply( null ,args);
})
}
这还是 connect 兼容以前的 es5 之类的方法。如果在 es6 下面,方法可以再次简化
function (..args){ process.nextTick(fn.bind(...args)) } 总结
connect 做为 http 中间件模块,很好地解决对 http 请求的插件化处理的需求,把中间件组织成请求上的一个处理器,挨个调用中间件对 http 请求进行处理。
其中 connect 的递归调用,和对 js 的函数对象的使用,让值得学习,如果让我来写,就第一个调个的地方,就想不到使用 函数对象 来进行处理。
而且 next 的设计如此精妙,整个框架的使用和概念上,对程序员基本上没有认知负担,这才是最重要的地方。这也是为什么 express 框架最受欢迎。koa 相比之下,多几个概念,还使用了不常用的 yield 方法。
connect 的设计理念可以用在,类似 http 请求模式上, 如 rpc, tcp 处理等。









