1.app.use的原理是什么?
作用:
- express 的这个中间件架构就是负责管理与调用这些注册的中间件
- 中间件顺序执行,通过 next 来继续下一个,一旦没有继续next,则流程结束
app.use 原理:
- 先会进入 applications 中的 app.use 函数去判断参数是啥,如果是应用中间件,就会默认加上 path=’/’
- 然后会调用 router.use,在该方法中会创建 Layer 对象,存储每个中间件函数的信息
- 在把这些 Layer 对象 push 到每个路由的 stack 数组中
- 当 http 请求时,app 就会从 stack 数组中逐个取出,进行匹配过滤,逐个运行
- 遍历完成后,运行 finalhandler,结束一个 http 请求
// app.use 在 applications.js中可以找到
app.use = function use(fn) {
var offset = 0
var path = '/'
// 省略...
var fns = flatten(slice.call(arguments, offset));
// 创建路由对象
this.lazyrouter();
var router = this._router;
fns.forEach(function (fn) {
// 省略...
// 可以看出最后还是调用 router.use 函数
router.use(path, function mounted_app(req, res, next) {
var orig = req.app;
fn.handle(req, res, function (err) {
setPrototypeOf(req, orig.request)
setPrototypeOf(res, orig.response)
next(err);
});
});
fn.emit('mount', this);
}, this);
return this;
};
// route.use 在 router/index.js 中可以找到
proto.use = function use(route, callback) {
var offset = 0
// 拿到所有的回调函数
var callbacks = flatten(slice.call(arguments, offset))
for (var i = 0; i < callbacks.length; i++) {
var fn = callbacks[i]
// 创建一个 layer 实例
var layer = new Layer(path, {
sensitive: this.caseSensitive,
strict: false,
end: false
}, fn)
layer.route = undefined
// 将 layer 实例存入 stack 数组中
this.stack.push(layer)
}
return this
}