使用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);

 

express源码剖析2的更多相关文章

  1. express源码剖析1

    在通读源码之前,先把一些比较难理解的代码吃透: 1.EventEmitter.prototype mixin(app, EventEmitter.prototype, false); app为一个函数 ...

  2. express源码剖析--Router模块

    1.加载模块执行代码: methods.forEach(function(method){ //method是http协议的各种请求方法,如:get,put,headee,post Route.pro ...

  3. Node 进阶:express 默认日志组件 morgan 从入门使用到源码剖析

    本文摘录自个人总结<Nodejs学习笔记>,更多章节及更新,请访问 github主页地址.欢迎加群交流,群号 197339705. 章节概览 morgan是express默认的日志中间件, ...

  4. STL源码剖析——hashtable

    二叉搜索树具有对数时间的搜索复杂度,但是这样的复杂度是再输入数据有足够的随机性的假设上哈希表在插入删除搜索操作上也具有常数时间的表现,而且这种表现是以统计为基础,不需要依赖输入元素的随机性 hasht ...

  5. jQuery之Deferred源码剖析

    一.前言 大约在夏季,我们谈过ES6的Promise(详见here),其实在ES6前jQuery早就有了Promise,也就是我们所知道的Deferred对象,宗旨当然也和ES6的Promise一样, ...

  6. Nodejs事件引擎libuv源码剖析之:高效线程池(threadpool)的实现

    声明:本文为原创博文,转载请注明出处. Nodejs编程是全异步的,这就意味着我们不必每次都阻塞等待该次操作的结果,而事件完成(就绪)时会主动回调通知我们.在网络编程中,一般都是基于Reactor线程 ...

  7. Apache Spark源码剖析

    Apache Spark源码剖析(全面系统介绍Spark源码,提供分析源码的实用技巧和合理的阅读顺序,充分了解Spark的设计思想和运行机理) 许鹏 著   ISBN 978-7-121-25420- ...

  8. 基于mybatis-generator-core 1.3.5项目的修订版以及源码剖析

    项目简单说明 mybatis-generator,是根据数据库表.字段反向生成实体类等代码文件.我在国庆时候,没事剖析了mybatis-generator-core源码,写了相当详细的中文注释,可以去 ...

  9. STL"源码"剖析-重点知识总结

    STL是C++重要的组件之一,大学时看过<STL源码剖析>这本书,这几天复习了一下,总结出以下LZ认为比较重要的知识点,内容有点略多 :) 1.STL概述 STL提供六大组件,彼此可以组合 ...

随机推荐

  1. P143、面试题25:二叉树中和为某一值的路径

    题目:输入一棵二叉树和一个整数,打印出二叉树中结点值的和为输入整数的所有路径.从树的根结点开始往下一直到叶结点所经过的结点形成一条路径.二叉树结点的定义如下:struct BinaryTreeNode ...

  2. ssh-keygen的使用方法

    一.概述 1.就是为了让两个linux机器之间使用ssh不需要用户名和密码.采用了数字签名RSA或者DSA来完成这个操作 2.模型分析 假设 A (192.168.20.59)为客户机器,B(192. ...

  3. 转:JS日期加减,日期运算

    原文 出处http://hi.baidu.com/tonlywang/item/685fba8933a2a756e73d1950 一.日期减去天数等于第二个日期 function cc(dd,dadd ...

  4. Android 签名(7)签名常见问题,debug签名和release签名的区别等

    一般在安装时提示出错:INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES 1) 两个应用,名字相同,签名不同 2) 升级时前一版本签名,后一版本没签名 3) ...

  5. git rebase无法处理的问题

    在进行代码整理的时候,遇到了冲突 现在chucklu_master分支指向这个commit SHA-1: 88fa1ee9263402626d85b5a4362e1b620935953f * remo ...

  6. Ubuntu 12.04下搭建Qt开发环境

    http://download.qt.io/official_releases/qt/ Ubuntu 环境下Gtk与Qt编译环境安装与配置(系统环境是Ubuntu 12.04) 1.配置基础开发环境G ...

  7. bzoj2906

    显然分块,由于颜色也有区间,我们的ans[l,r,k]表示块l和块r颜色1~k的权值和所以我们块的大小要设为n^(2/3),其它没什么说的,比较水 ..,..,..] of int64; g:..,. ...

  8. UVa 808 (建坐标系、找规律) Bee Breeding

    题意: 如图,按照图中的规律给这些格子编号.给出两个格子的编号,求从一个格子到另一个格子的最少步数.(一步只能穿过有有公共边的格子) 分析: 根据高中数学知识,选任意两个不共线的向量,就能表示平面上所 ...

  9. I.MX6 Linux 自动获取AR1020 event input节点

    /*********************************************************************** * I.MX6 Linux 自动获取AR1020 ev ...

  10. I.MX6 PMU MMPF0100 driver porting

    /************************************************************************** * I.MX6 MMPF0100 driver ...