《关于洋葱模型》

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
const Koa = require("koa");

const app = new Koa();
const PORT = 3000;

// #1
app.use(async (ctx, next) => {
console.log(1);
await next(); //暂停当前程序
console.log(1);
});
// #2
app.use(async (ctx, next) => {
console.log(2);
await next(); //暂停当前程序
console.log(2);
});

app.use(async (ctx, next) => {
console.log(3);
});

app.listen(PORT);
console.log(`http://localhost:${PORT}`);

输出

1
2
3
4
5
1
2
3
2
1

在 koa 中,app.use 注册的中间件的回调按照洋葱模型迭代的。中间件被 next()方法分成了两部分。next()方法上面部分会先执行。next()方法下面的部分会在后面的中间件执行全部结束后执行。

洋葱内的每一层都表示一个独立的中间件,用于实现不同的功能,比如异常处理、缓存处理等。每次请求都会从左侧开始一层层地经过每层的中间件,当进入到最里层的中间件之后,就会从最里层的中间件开始逐层返回。因此对于每层的中间件来说,在一个 请求和响应 周期中,都有两个时机点来添加不同的处理逻辑。

洋葱模型可以干什么?
比如计算一次请求的耗时,且获取其他中间件的信息,如果没有洋葱模型是没有办法实现的。

例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
const Koa = require("koa");

const app = new Koa();
const PORT = 3000;

// #1
app.use((ctx, next) => {
let start = Date.now();
console.log(1);
next(); //暂停当前程序
let end = Date.now();
console.log(end - start);
console.log(1);
});
// #2
app.use(async (ctx, next) => {
console.log(2);
await axios.get("XXX.com/api/XXX");
console.log(2);
});

上述代码不是洋葱模型,所以他是计算不出发请求所用时间的,当我们保证他是洋葱模型后他就能计算出一个请求发出到接收数据所用时间。