一、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运行原理的更多相关文章

  1. Asp.net WebPages框架运行原理浅析(转)

    在Asp.net4和4.5中,新增了WebPages Framework,编写页面代码使用了新的Razor语法,代码更加的简洁和符合Web标准,编写方式更接近于PHP和以前的Asp,和使用 WebFo ...

  2. ASP.NET的运行原理与运行机制

    在Asp.net4和4.5中,新增了WebPages Framework,编写页面代码使用了新的Razor语法,代码更加的简洁和符合Web标准,编写方式更接近于PHP和以前的Asp,和使用WebFor ...

  3. iBatis.Net的基本情况和运行原理

    转载http://www.cnblogs.com/13590/archive/2013/02/27/2934580.html 摘要:介绍iBatis.Net的基本情况和运行原理,运行环境中各参数的配置 ...

  4. Asp.net WebPages框架运行原理浅析

    [来源] 达内    [编辑] 达内   [时间]2012-09-14 在Asp.net4和4.5中,新增了WebPages Framework,编写页面代码使用了新的Razor语法,代码更加的简洁和 ...

  5. 【原创】分布式之数据库和缓存双写一致性方案解析(三) 前端面试送命题(二)-callback,promise,generator,async-await JS的进阶技巧 前端面试送命题(一)-JS三座大山 Nodejs的运行原理-科普篇 优化设计提高sql类数据库的性能 简单理解token机制

    [原创]分布式之数据库和缓存双写一致性方案解析(三)   正文 博主本来觉得,<分布式之数据库和缓存双写一致性方案解析>,一文已经十分清晰.然而这一两天,有人在微信上私聊我,觉得应该要采用 ...

  6. Serverless 的运行原理与组件架构

    本文重点探讨下开发者使用 Serverless 时经常遇到的一些问题,以及如何解决 过去一年,我们和大量 Serverless 用户进行了线上和线下的交流,了解大家的业务场景.对 Serverless ...

  7. iis6.0与asp.net的运行原理

    这几天上网翻阅了不少前辈们的关于iis和asp.net运行原理的博客,学的有点零零散散,花了好长时间做了一个小结(虽然文字不多,但也花了不少时间呢),鄙人不才,难免有理解不道的地方,还望前辈们不吝赐教 ...

  8. ASP.NET Core 运行原理剖析2:Startup 和 Middleware(中间件)

    ASP.NET Core 运行原理剖析2:Startup 和 Middleware(中间件) Startup Class 1.Startup Constructor(构造函数) 2.Configure ...

  9. ASP.NET Core 运行原理剖析1:初始化WebApp模版并运行

    ASP.NET Core 运行原理剖析1:初始化WebApp模版并运行 核心框架 ASP.NET Core APP 创建与运行 总结 之前两篇文章简析.NET Core 以及与 .NET Framew ...

随机推荐

  1. 杨涛老师MvcPager示例

    杨涛老师插件地址:http://www.webdiyer.com/mvcpager 杨涛老师网站上示例写的很详细了,参考他的示例和帮助文档就可以运用的很好了,有经验的同学可以直接参考官方示例. 一.标 ...

  2. bashrc profile的区别

    bashrc与profile的区别 bashrc和profile的差异在于:1. bashrc是在系统启动后就会自动运行.2. profile是在用户登录后才会运行.3. 进行设置后,可运用sourc ...

  3. C#获取当前时区转换方法

    今天给Mongodb插入数据的时候发现,日期时间对不上,原来Mongodb(麻狗)默认是0时区,所以日期当然出错. 所以用下面进行转换就可以: log.AddTime = DateTime.Speci ...

  4. 纯CSS实现瀑布流布局

    https://www.w3cplus.com/css/pure-css-create-masonry-layout.html

  5. 《倾国倾城》全套源代码:client+服务端+资源,歧视复制帖子

    郝萌主倾心贡献,尊重作者的劳动成果,请勿转载. 假设文章对您有所帮助,欢迎给作者捐赠,支持郝萌主,捐赠数额任意.重在心意^_^ 我要捐赠: 点击捐赠 Cocos2d-X源代码下载:点我传送 游戏官方下 ...

  6. Java从控制台接受输入字符

    创建一个类,在该类的主方法中创建Scanner扫描起来封装System类的in输入流,然后提示用户输入身份证号码,并输入身份证号码的位数. 代码如下: import java.util.Scanner ...

  7. Hadoop核心架构HDFS+MapReduce+Hbase+Hive内部机理详解

    转自:http://blog.csdn.net/iamdll/article/details/20998035 分类: 分布式 2014-03-11 10:31 156人阅读 评论(0) 收藏 举报 ...

  8. JTAG、JLink、ULINK、ST-LINK仿真器区别(转)

    首先要了解一下JTAG. JTAG协议 JTAG(Joint Test Action Group,联合测试行动小组)是一种国际标准测试协议(IEEE 1149.1兼容),主要用于芯片内部测试.现在多数 ...

  9. 敏感词过滤和XML的创建

    今天我慢下来啦,因为这三天没有新的课程学习内容,自己仅仅看啦一些,这让我停下来栖息片刻:说说现在的生活,简单的进行着,每天要奔波着去上课,然后回来,每天都在想怎样学习这个小知识点,大脑也在想怎样解决程 ...

  10. C++程序中调用其他exe可执行文件方法

    在编程过程中有个需求,点击某个按钮需要弹出系统的声音控制面板.在网上查了下代码中调用其他exe程序或者打开其他文件的方法. 自己借鉴网上的文章稍微总结下,加深下印象,也给方便自己用. 在代码中调用其他 ...