express源码剖析2

使用express时,代码会这样写:

var express = require('express');

创建一个express的应用,代码:

var app = express();

那么express()是什么?它执行createApplication()

//express.js
exports = module.exports =createApplication;
/**
 * Create an express application.
 *
 * @return {Function}
 * @api public
 */

function createApplication() {
  var app = function(req, res, next) {
    app.handle(req, res, next);
  };

  mixin(app, EventEmitter.prototype, false);
  mixin(app, proto, false);

  app.request = { __proto__: req, app: app };
  app.response = { __proto__: res, app: app };
  app.init();
  return app;  
  //执行的结果就是app是一个实例,它有私有成员对象:request和 response,同时继承Event模块中的EventEmitter的原型。
}

在express.js中,要区分下面两个包:

var Route = require('./router/route');
var Router = require('./router');
//对外都暴露Route和Router,他们两者有些不同,
//Router是Route的超集,两者的联系只在Router.route用到。调用Router.route会得到一个route,不过给Router.stack添加了一个Layer,
//该Layer通过Router的参数和route.dispatch和用户的path来定义的。
//route只有三个成员,stack数组(储存Layer对象),path(路由的路径)和method对象。
//其中stack数组与Router一样,同时两个对象的原型都有methods的和all的方法
exports.Route = Route;
exports.Router = Router;

express也继承了application.js中的方法。执行app.init();

app.init = function init() {
 //给app类/对象赋值三个公用成员, 在初始的过程中,有一个成员变量很关键,就是router
  this.cache = {};
  this.engines = {};
  this.settings = {};
  // 初始化配置,在研究defaultConfiguration之前,抽象下app.set函数,它就是给setting赋值的函数,同时针对key = "etag" 和 query parser以及"trust proxy"进行特殊的的设置。
  this.defaultConfiguration();
};

app还挂有很多方法,这些可以在express的api中的application的方法找到!其中最重要的方法是app.use,它用来构造路由所执行的函数的一个数据结构_router,express在执行过程中,会遍历这个结构。

 1.1app.use方法

//use的使用
var express = require('express');
var app = express();
function handlerWrap(){
    console.log("1");
}
app.use("/", handlerWrap);                //路径/会调用hanlerWrap方法

 app.use源码

this.lazyrouter();  
app.lazyrouter = function lazyrouter() {
//给a公有变量_router赋值,它是对象Router的实例。
if (!this._router) {
//实例化Router
this._router = new Router({
     caseSensitive: this.enabled('case sensitive routing'),   //false
     strict: this.enabled('strict routing')                   //false 
 });
//router.use(path,fn);  为path建立layer,有多少个fn,就建立多少个Layer,然后把这个layer压入router.stack数组中。初始定义了两个Layer
this._router.use(query(this.get('query parser fn'))); 
    //this.get('query parser fn')为一个函数:
    this._router.use(middleware.init(this));
   }
};  
if (!fn || !fn.handle || !fn.set) {
      //handlerWrap函数为handler、 set成员!,如果fn函数没有handle,或者set函数,调用router.use(path,fn)。也就是说那不是express的实例,大部分插件都会直接执行。
      return router.use(path, fn);  //rounter.use直接把该函数构造成一个Layer成员,实际上是给router.stack添加一个layer成员。
 }
 debug('.use app under %s', path);
 fn.mountpath = path;          //如果是express的对象,那么给express这个对象成员mountpath赋值为path(可能含有正则);
 fn.parent = this;             //fn变成子express对象,当前的express为父。
 // restore .app property on req and res   //执行use,封装了fn,
router.use(path, function mounted_app(req, res, next) {
 var orig = req.app;               //这里看的不太懂。      
   fn.handle(req, res, function (err) {
     req.__proto__ = orig.request;
     res.__proto__ = orig.response;
     next(err);
     });
});
// mounted an app
console.log("fn="+JSON.stringify(fn));
fn.emit('mount', this);
 // 进入router/index.js中,执行proto.use()方法。
 // 实际上是给router.stack添加一个layer成员,
  var layer = new Layer(path, {
    sensitive: this.caseSensitive,
    strict: false,
    end: false
  }, fn);
  layer.route = undefined;  //给layer.route赋值undefined
   this.stack.push(layer);

 

原文地址:https://www.cnblogs.com/liuyinlei/p/6264677.html