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 ...
随机推荐
- 杨涛老师MvcPager示例
杨涛老师插件地址:http://www.webdiyer.com/mvcpager 杨涛老师网站上示例写的很详细了,参考他的示例和帮助文档就可以运用的很好了,有经验的同学可以直接参考官方示例. 一.标 ...
- bashrc profile的区别
bashrc与profile的区别 bashrc和profile的差异在于:1. bashrc是在系统启动后就会自动运行.2. profile是在用户登录后才会运行.3. 进行设置后,可运用sourc ...
- C#获取当前时区转换方法
今天给Mongodb插入数据的时候发现,日期时间对不上,原来Mongodb(麻狗)默认是0时区,所以日期当然出错. 所以用下面进行转换就可以: log.AddTime = DateTime.Speci ...
- 纯CSS实现瀑布流布局
https://www.w3cplus.com/css/pure-css-create-masonry-layout.html
- 《倾国倾城》全套源代码:client+服务端+资源,歧视复制帖子
郝萌主倾心贡献,尊重作者的劳动成果,请勿转载. 假设文章对您有所帮助,欢迎给作者捐赠,支持郝萌主,捐赠数额任意.重在心意^_^ 我要捐赠: 点击捐赠 Cocos2d-X源代码下载:点我传送 游戏官方下 ...
- Java从控制台接受输入字符
创建一个类,在该类的主方法中创建Scanner扫描起来封装System类的in输入流,然后提示用户输入身份证号码,并输入身份证号码的位数. 代码如下: import java.util.Scanner ...
- Hadoop核心架构HDFS+MapReduce+Hbase+Hive内部机理详解
转自:http://blog.csdn.net/iamdll/article/details/20998035 分类: 分布式 2014-03-11 10:31 156人阅读 评论(0) 收藏 举报 ...
- JTAG、JLink、ULINK、ST-LINK仿真器区别(转)
首先要了解一下JTAG. JTAG协议 JTAG(Joint Test Action Group,联合测试行动小组)是一种国际标准测试协议(IEEE 1149.1兼容),主要用于芯片内部测试.现在多数 ...
- 敏感词过滤和XML的创建
今天我慢下来啦,因为这三天没有新的课程学习内容,自己仅仅看啦一些,这让我停下来栖息片刻:说说现在的生活,简单的进行着,每天要奔波着去上课,然后回来,每天都在想怎样学习这个小知识点,大脑也在想怎样解决程 ...
- C++程序中调用其他exe可执行文件方法
在编程过程中有个需求,点击某个按钮需要弹出系统的声音控制面板.在网上查了下代码中调用其他exe程序或者打开其他文件的方法. 自己借鉴网上的文章稍微总结下,加深下印象,也给方便自己用. 在代码中调用其他 ...