express运行原理
一、express底层:http模块
Express框架建立在node.js内置的http模块上。http模块生成服务器的原始代码如下。
var http = require("http");
var app = http.createServer(function(request, response) {
  response.writeHead(, {"Content-Type": "text/plain"});
  response.end("Hello world!");
});
app.listen(, "localhost");
上面代码的关键是http模块的createServer方法,表示生成一个HTTP服务器实例。该方法接受一个回调函数,该回调函数的参数,分别为代表HTTP请求和HTTP回应的request对象和response对象。
Express框架的核心是对http模块的再包装。上面的代码用Express改写如下。
var express = require('express');
var app = express();
app.get('/', function (req, res) {
  res.send('Hello world!');
});
app.listen();
  比较两段代码,可以看到它们非常接近。原来是用http.createServer方法新建一个app实例,现在则是用Express的构造方法,生成一个Epress实例。两者的回调函数都是相同的。Express框架等于在http模块之上,加了一个中间层。
二、express中间件
简单说,中间件(middleware)就是处理HTTP请求的函数。它最大的特点就是,一个中间件处理完,再传递给下一个中间件。App实例在运行过程中,会调用一系列的中间件。
每个中间件可以从App实例,接收三个参数,依次为request对象(代表HTTP请求)、response对象(代表HTTP回应),next回调函数(代表下一个中间件)。每个中间件都可以对HTTP请求(request对象)进行加工,并且决定是否调用next方法,将request对象再传给下一个中间件。
一个不进行任何操作、只传递request对象的中间件,就是下面这样。
function uselessMiddleware(req, res, next) {
  next();
}
上面代码的next就是下一个中间件。如果它带有参数,则代表抛出一个错误,参数为错误文本。
function uselessMiddleware(req, res, next) {
  next('出错了!');
}
抛出错误以后,后面的中间件将不再执行,直到发现一个错误处理函数为止。
在 Node.js Web 开发中,各种模块基本采用这样的中间件格式:
function (req, res, next) {
  // req 用于获取请求信息, ServerRequest 的实例
  // res 用于响应处理结果, ServerResponse 的实例
  // next() 函数用于将当前控制权转交给下一步处理,如果给 next() 传递一个参数时,表示出错信息
}
Express 是基于 Connect 的, Connect 中间件采用了以上的这种格式。 因此,当你要编写一个中间件时,编写一个以上格式的函数即可。
其实跟编写 Express 的路由处理函数是没多大区别的,一些细微的差别是:
- 中间件一般不直接对客户端进行响应,而是对请求进行一些预处理,再传递下去;
- 中间件一般会在路由处理之前执行;
比如:
// 检查用户是否登录中间件,所有需要登录权限的页面都使用此中间件
function checkLogin (req, res, next) {
if (req.session.user) {
next();
} else {
res.redirect('/');
}
}
三、USE方法
use是express注册中间件的方法,它返回一个函数。下面是一个连续调用两个中间件的例子。
var express = require("express");
var http = require("http");
var app = express();
app.use(function(request, response, next) {
  console.log("In comes a " + request.method + " to " + request.url);
  next();
});
app.use(function(request, response) {
  response.writeHead(, { "Content-Type": "text/plain" });
  response.end("Hello world!\n");
});
http.createServer(app).listen(); 
  上面代码使用app.use方法,注册了两个中间件。收到HTTP请求后,先调用第一个中间件,在控制台输出一行信息,然后通过next方法,将执行权传给第二个中间件,输出HTTP回应。由于第二个中间件没有调用next方法,所以request对象就不再向后传递了。
use方法内部可以对访问路径进行判断,据此就能实现简单的路由,根据不同的请求网址,返回不同的网页内容。
var express = require("express");
var http = require("http");
var app = express();
app.use(function(request, response, next) {
  if (request.url == "/") {
    response.writeHead(, { "Content-Type": "text/plain" });
    response.end("Welcome to the homepage!\n");
  } else {
    next();
  }
});
app.use(function(request, response, next) {
  if (request.url == "/about") {
    response.writeHead(, { "Content-Type": "text/plain" });
  } else {
    next();
  }
});
app.use(function(request, response) {
  response.writeHead(, { "Content-Type": "text/plain" });
  response.end("404 error!\n");
});
http.createServer(app).listen(); 
  上面代码通过request.url属性,判断请求的网址,从而返回不同的内容。注意,app.use方法一共登记了三个中间件,只要请求路径匹配,就不会将执行权交给下一个中间件。因此,最后一个中间件会返回404错误,即前面的中间件都没匹配请求路径,找不到所要请求的资源。
除了在回调函数内部,判断请求的网址,use方法也允许将请求网址写在第一个参数。这代表,只有请求路径匹配这个参数,后面的中间件才会生效。无疑,这样写更加清晰和方便。
app.use('/', someMiddleware); 
上面代码表示,只对根目录的请求,调用某个中间件。
因此,上面的代码可以写成下面的样子。
var express = require("express");
var http = require("http");
var app = express();
app.use("/", function(request, response, next) {
  response.writeHead(, { "Content-Type": "text/plain" });
  response.end("Welcome to the homepage!\n");
});
app.use("/about", function(request, response, next) {
  response.writeHead(, { "Content-Type": "text/plain" });
  response.end("Welcome to the about page!\n");
});
app.use(function(request, response) {
  response.writeHead(, { "Content-Type": "text/plain" });
  response.end("404 error!\n");
});
http.createServer(app).listen();
参考资料:
http://javascript.ruanyifeng.com/nodejs/express.html
express运行原理的更多相关文章
- Asp.net WebPages框架运行原理浅析(转)
		在Asp.net4和4.5中,新增了WebPages Framework,编写页面代码使用了新的Razor语法,代码更加的简洁和符合Web标准,编写方式更接近于PHP和以前的Asp,和使用 WebFo ... 
- ASP.NET的运行原理与运行机制
		在Asp.net4和4.5中,新增了WebPages Framework,编写页面代码使用了新的Razor语法,代码更加的简洁和符合Web标准,编写方式更接近于PHP和以前的Asp,和使用WebFor ... 
- iBatis.Net的基本情况和运行原理
		转载http://www.cnblogs.com/13590/archive/2013/02/27/2934580.html 摘要:介绍iBatis.Net的基本情况和运行原理,运行环境中各参数的配置 ... 
- Asp.net WebPages框架运行原理浅析
		[来源] 达内 [编辑] 达内 [时间]2012-09-14 在Asp.net4和4.5中,新增了WebPages Framework,编写页面代码使用了新的Razor语法,代码更加的简洁和 ... 
- 【原创】分布式之数据库和缓存双写一致性方案解析(三)  前端面试送命题(二)-callback,promise,generator,async-await  JS的进阶技巧  前端面试送命题(一)-JS三座大山  Nodejs的运行原理-科普篇  优化设计提高sql类数据库的性能  简单理解token机制
		[原创]分布式之数据库和缓存双写一致性方案解析(三) 正文 博主本来觉得,<分布式之数据库和缓存双写一致性方案解析>,一文已经十分清晰.然而这一两天,有人在微信上私聊我,觉得应该要采用 ... 
- Serverless 的运行原理与组件架构
		本文重点探讨下开发者使用 Serverless 时经常遇到的一些问题,以及如何解决 过去一年,我们和大量 Serverless 用户进行了线上和线下的交流,了解大家的业务场景.对 Serverless ... 
- iis6.0与asp.net的运行原理
		这几天上网翻阅了不少前辈们的关于iis和asp.net运行原理的博客,学的有点零零散散,花了好长时间做了一个小结(虽然文字不多,但也花了不少时间呢),鄙人不才,难免有理解不道的地方,还望前辈们不吝赐教 ... 
- ASP.NET Core 运行原理剖析2:Startup 和 Middleware(中间件)
		ASP.NET Core 运行原理剖析2:Startup 和 Middleware(中间件) Startup Class 1.Startup Constructor(构造函数) 2.Configure ... 
- ASP.NET Core 运行原理剖析1:初始化WebApp模版并运行
		ASP.NET Core 运行原理剖析1:初始化WebApp模版并运行 核心框架 ASP.NET Core APP 创建与运行 总结 之前两篇文章简析.NET Core 以及与 .NET Framew ... 
随机推荐
- Mac OS终端中设置颜色高亮和自动补全
			已测试通过,原文:http://blog.csdn.net/songjinshi/article/details/8945809 一.颜色高亮显示 针对terminal采用bash模式: 编辑 ~/. ... 
- ubuntu 4.10~5.10 :古老的ubuntu上安装oracle10g的情况
			64位的: 不用想了,安装不上,因为ubuntu库里没有提供编译环境:安装不上gcc-multilib库.也没有libc6-dev-i386库! 自己这点水平,真搞不定! 32位的: 很顺利.很顺利! ... 
- ubuntu 的chmod 和 chown
			1.chown改文件或目录的所有者和群组权限 格式 chown [OPTION]... [OWNER][:[GROUP]] FILE... 参数: -R 递归操作当前目录下的所有目录和文件: -h 更 ... 
- Linux中/etc/resolv.conf文件简析
			https://blog.csdn.net/lcr_happy/article/details/54867510 
- 利用MsChart控件绘制多曲线图表(转载)
			在.Net4.0框架中,微软已经将Mschart控件集成了进来,以前一直在web下面用过,原来winform下的Mschart控件更加简单更加方便,今天我们用mschart绘制一个多曲线图,话不多说, ... 
- 【剑指Offer学习】【面试题23:从上往下打印二叉树】
			题目:从上往下打印出二叉树的每一个结点,同一层的结点依照从左向右的顺序打印. 二叉树结点的定义: public static class BinaryTreeNode { int value; Bin ... 
- mysql强制使用索引
			在公司后台某模块功能记录日志中有一个搜索功能,通过前段时间的产品使用时间区间进行搜索反馈有些卡顿,我发现这个搜索功能比较慢,要3秒左右才能出来,就决定对这里做一下优化. 通过分析代码和SQL发现最核心 ... 
- WPF路由事件学习(一)
			路由事件与一般事件的区别在于:路由事件是一种用于元素树的事件,当路由事件触发后,它可以向上或向下遍历可视树和逻辑树,他用一种简单而持久的方式在每个元素上触发,而不需要任何定制的代码(如果用传统的方式实 ... 
- 【GIS】Cesium回到初始位置
			var boundingSphere = new Cesium.BoundingSphere(Cesium.Cartesian3.fromDegrees(116.4, 39.9, 100), 15 ... 
- 【代码审计】XIAOCMS_存在任意文件删除漏洞分析
			0x00 环境准备 XIAOCMS官网: http://www.xiaocms.com/ 网站源码版本:XiaoCms (发布时间:2014-12-29) 程序源码下载:http://www.xi ... 
