Express和Koa是目前最主流的基于node的web开发框架,他们的开发者是同一班人马。貌似如今Koa更加流行,可是仍然有大量的项目在使用Express,因此我想经过这篇文章说说Express中间件的原理。html
中间件的本质就是一个函数,在收到请求和返回相应的过程当中作一些咱们想作的事情。Express文档中对它的做用是这么描述的:node
执行任何代码。
修改请求和响应对象。
终结请求-响应循环。
调用堆栈中的下一个中间件。
git
Express文档中把他们分为了五类,可是他们的原理相同,只是用法不一样:github
应用级中间件
路由级中间件
错误处理中间件
内置中间件
第三方中间件
web
首先咱们看看中间件的用法:express
var express = require('express')
var app = express();
app.use('/user', function (req, res, next) {
//TODO
next();
});
app.listen(8080)
复制代码
接下来咱们对比看一下下源码:api
先看express.js的代码:数组
这部分代码中最重要的是红色方框部分,mixin
是一个第三方库。能够简单理解为继承(实际上它不是继承而是混合)。
bash
接下来咱们看application.js:app
我把文件下载下来而且删去了注释,经过这张图咱们能够看出这个文件的做用是挂载了全部的方法(包括use等关键api)。
这里面比较重要的是use
方法,它的做用就是把咱们用app.use
注册的全部中间件和路由方法交给Router
类来处理。
那咱们再看看router文件夹类的结构:
index.js是入口文件,处理全部的路由;
layer.js中声明了Layer
类,处理每一层路由中间件或者每个子中间件;
router.js中声明了Router
类,处理每个子路由。
这里面有一个子中间件的概念,对应Exprees文档中有这一句话:
另外,你还能够同时装载一系列中间件函数,从而在一个挂载点上建立一个子中间件栈。
这句话的意思是说咱们能够把代码写成下面这种形式:
app.use('/user1', function fn1(req, res, next) {
// TODO
next();
}, function fn2(req, res, next) {
//TODO
next();
});
app.use('/user2', function fn3(req, res, next) {
// TODO
next();
}, function fn4(req, res, next) {
//TODO
next();
});
复制代码
上面的代码给user1和user2分别建立了一个子中间件栈。这种语法的实现就是靠Layer
类实现的。
画一张图来解释上面的代码:
解释一下上面的代码和图:
咱们写了两个路由/user1和/user2,每一个路由给了两个处理函数。对于这段代码,Express是这样处理的:
stack
数组,接下来会建立两个Layer
放到这个stack
中。stack
和fn一、fn2两个Layer
。Layer
里的函数,对应到图上就是从上至下、从左至右的依次执行,顺序为fn一、fn二、fn三、fn4。以上就是Express中间件的简单原理,白话较多,若是写的不许确的地方,但愿你们批评指正。