中间件,对新手来说又是个不明觉厉的词汇,简单地说,几乎所有的应用都是一个服务器收发的过程,客户端通过http发送请求,服务器收到请求后给出响应,这是整个互联网的运作方式,而中间件,顾名思义,就是在收发之间做逻辑处理。

业界有句名言:

计算机科学领域的任何问题都可以通过增加一个间接的中间层来解决
“Any problem in computer science can be solved by anther layer of indirection.”

仔细想一下很多问题都是通过添加独立的层的概念来解决的,包括一些已经作为常识的知识,比如:互联网层的划分,从底层的物理层,到上层的应用层,彼此层之间相互独立,各司其职,以后再有什么升级或改动,保证原有层不变的基础上,添加一个层承上启下,即可。比如HTTPS就是在HTTP的基础上多了一层加密层。

而中间件的概念貌似也是如此。一个中间件就是一个功能层,相互独立,各司其职。

以express中间件为例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
var express = require('express');
var app = express();
app.listen(3000, function () {
console.log('listen 3000...');
});
app.use(middleware1);
app.use(middleware2);
app.use(middleware3);
function middleware1(req, res, next){
console.log("我是1");
next();
console.log("我是1,out");
}
function middleware2(req, res, next){
console.log("我是2");
next();
console.log("我是2,out");
}
function middleware3(req, res, next){
console.log("我是3");
next();
console.log("我是3,out");
}

app.use方法用来接收中间件1、2、3,其执行结果为:

1
2
3
4
5
6
7
listen 3000...
我是1
我是2
我是3
我是3,out
我是2,out
我是1,out

为什么遇到next后就直接跳转,等所有next执行完毕才回溯执行各自next后面的代码呢?app.use内部又是怎么回事呢?

原理

从结果可以看出,多个中间件的执行顺序是按栈结构执行的,首先遇到next跳转到下一个中间件执行,直到最内部的中间值执行完毕后,才执行最内部中间件next后面的代码,执行完后才返回上一层执行上一层中间件next后面的代码,像极了洋葱图。

而在代码层面上,每当调用app.use添加中间件时,其实内部维护了一个数组,把这些追加的中间件push进去,然后反方向执行,先执行数组最末端的中间件,直到第一个push进去的中间件,这样就实现了上述中间件调用效果。demo: