nodejs模块学习之connect解析

2020-06-17 06:38:57易采站长站整理

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 处理等。