return ;
}
// route data
var path = parseUrl(req).pathname || '/' ;
var route = layer.route;
// skip this layer if the route doesn't match
if (path.toLowerCase().substr(0, route.length) !== route.toLowerCase()) {
return next(err); // 执行下一个
}
// skip if route match does not border "/", ".", or end
var c = path[route.length];
if (c !== undefined && '/ ' !== c && ' . ' !== c) {
return next(err); // 执行下一个
}
// trim off the part of the url that matches the route
if (route.length !== 0 && route !== ' / ') {
removed = route;
req.url = protohost + req.url.substr(protohost.length + removed.length);
// ensure leading slash
if (!protohost && req.url[0] !== ' / ') {
req.url = ' /' + req.url;
slashAdded = true ;
}
}
// call the layer handle
call(layer.handle, route, err, req, res, next);
}
next();
};
代码中有相应的注释,可以看出,next 方法就是一个递归调用,不断的对比 route 是否匹配,如果匹配则调用 handle, 如果不匹配,则调用下一个 handle.
call 函数的代码如下:
function call(handle, route, err, req, res, next) { var arity = handle.length;
var error = err;
var hasError = Boolean(err);
debug( '%s %s : %s' , handle.name || '<anonymous>' , route, req.originalUrl);
try {
if (hasError && arity === 4) {
// error-handling middleware
handle(err, req, res, next);
return ;
} else if (!hasError && arity < 4) {
// request-handling middleware
handle(req, res, next);
return ;
}
} catch (e) {
// replace the error
error = e;
}
// continue
next(error);
}
可以看出一个重点:对错误处理,connect 的要求 是函数必须是 四个参数,而 express 也是如此。如果有错误, 中间件没有一个参数的个数是 4, 就会错误一直传下去,直到后面的 defer(done, err); 进行处理。
还有 app.use 添加中间件:
proto.use = function use(route, fn) { var handle = fn; // fn 只是一个函数的话 三种接口 // 1. err, req, res, next 2. req, res, 3, req, res, next
var path = route;
// default route to '/'
if ( typeof route !== 'string' ) {
handle = route;
path = '/' ;
}
// wrap sub-apps
if ( typeof handle.handle === 'function' ) { // 自定义中的函数对象









