// all done
if (!layer) {
defer(done, err); // ????? 为什么这里要用defer异步调用回调函数done?
return;
}
上面代码是connect.js中handle函数的代码,layer中间件运行完之后由defer异步调用最后的回调函数done。
express.js和socket.io中也是类似这样调用的,区别是express.js直接用的setImmediate,socket.io里用的process.nextTick。
在connect.js的代码历史中,只注释了这么一句:
Correctly invoke async callback asynchronously
setImmediate和process.nextTick的区别我能搞清楚,这里我的问题是为什么这里要异步调用?直接done(err)有什么不好的地方吗?我试过注释这句话直接调用,重跑了测试用例也没发现问题。
下面是链接和相关代码:
/* istanbul ignore next */
var defer = typeof setImmediate === 'function'
? setImmediate
: function(fn){ process.nextTick(fn.bind.apply(fn, arguments)) }
/**
* Handle server requests, punting them down
* the middleware stack.
*
* @private
*/
proto.handle = function handle(req, res, out) {
var index = 0;
var stack = this.stack;
// final function handler
var done = out || finalhandler(req, res, {
env: env,
onerror: logerror
});
function next(err) {
// next callback
var layer = stack[index++];
// all done
if (!layer) {
defer(done, err); // ????? 为什么这里要用defer异步调用done函数?
return;
}
// route data
var path = parseUrl(req).pathname || '/';
var route = layer.route;
// call the layer handle
call(layer.handle, route, err, req, res, next);
}
next();
};