使用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. minicom 配置

    问题: 1:不相应按键,只有打印 Hardware Flow Control 选择NO minicom显示中文的设置:              env LANG=en_US minicom   可以 ...

  2. Servlet课程0426(九)Servlet服务器端创建Cookie和客户端读取Cookie

    服务器端创建Cookie: Win7默认Cookie位置 C:\Users\Administrator\AppData\Roaming\Microsoft\Windows\Cookies Cookie ...

  3. WCF服务运行一段时间后客户端无法连接WCF服务的解决办法 (转)

    WCF服务运行一段时间后客户端无法连接WCF服务的解决办法 (转) Windows Communication Foundation (WCF)是Microsoft为构建面向服务的应用提供的分布式通信 ...

  4. foreman1.3安装

    一.环境: centos 6.3 64bit 二.安装yum源: rpm -ivh http://dl.fedoraproject.org/pub/epel/6/x86_64/epel-release ...

  5. 解决Eclipse导出javadoc乱码问题

    在Eclipse里 export 选 JavaDoc,在向导的最后一页的Extra JavaDoc Options 里填上参数即可 比如项目采用的是UTF-8的编码就填:-encoding UTF-8 ...

  6. Codeforces 364A - Matrix

    原题地址:http://codeforces.com/problemset/problem/364/A 题目大意: 给定一个数字a(0 ≤ a ≤ 109)和一个数列s(每个数都是一位,长度不超过40 ...

  7. Ext入门学习系列(四)面板控件

    第四章 使用面板 上节学习了Ext复杂对话框,更进一步了解了Ext的运行机制.本章重点来了解Ext所有控件的基础——面板控件. 一.Ext的面板是什么? 同样先来看看几个效果: 基本面板,点击右上角小 ...

  8. Fine Uploader文件上传组件

    最近在处理后台数据时需要实现文件上传.考虑到对浏览器适配上采用Fine Uploader. Fine Uploader 采用ajax方式实现对文件上传.同时在浏览器中直接支持文件拖拽[对浏览器版本有要 ...

  9. [Bhatia.Matrix Analysis.Solutions to Exercises and Problems]ExI.2.10

    (1). The numerical radius defines a norm on $\scrL(\scrH)$. (2). $w(UAU^*)=w(A)$ for all $U\in \U(n) ...

  10. 单点登录技术:微软Passport单点登录协议和自由联盟规范

    随着互联网络应用的普及,越来越多的人开始使用互联网上提供的服务.然而目前提供服务的网站大多采用用户名.口令的方式来识别用户身份,这使得用户需要经常性的输入自己的用户名.口令.显然这种认证方式存在着弊端 ...