Koa中间件
中间件本质就是一个函数
如何将函数变成一个函数
使用
app.use()
const Koa = require('koa')
function test() {
console.log('hello, world')
}
app.use(test)
app.listen(3000)
- 控制台启动程序
node app.js
- 浏览器访问
localhost:3000
, - 控制台输出
hello world
更常见的用法
// 用匿名函数 直接替换具名函数
app.use(() => {
console.log('hello world2')
})
// output: hello world2
中间件执行顺序
app.use(() => {
console.log('hello world')
});
app.use(() => {
console.log('hello world2')
});
// 执行结果: 只有 hello world 没有hello world2
node 中间件执行顺序是只会执行第一个注册的中间件。
执行多个中间件
app.use((ctx, next) => {
console.log('hello world')
next() // 下一个中间件函数
})
app.use(() => {
console.log('hello world2')
})
// output: hello world hello world2
koa中会默认用next代表下一个中间件
Koa 洋葱模型
我们先将上面代码改造下
app.use((ctx, next) => {
console.log('hello world1')
next()
console.log('hello world2')
})
app.use((ctx, next) => {
console.log('hello world3')
next()
console.log('hello world4')
})
// 很容易就能执行结果: 1 3 4 2 对吧
// 顺序是 中间件1的上 -> 中间件2的上 -> 中间件(next) -> 中间件2的下 -> 中间件1的下
有人问了,怎么跟我看到的不一样?
我们想想这样的场景,如果next里面需要调用异步的方法,怎么办?
使用async await
app.use(async (ctx, next) => {
console.log('hello world1')
await next()
console.log('hello world2')
})
app.use(async (ctx, next) => {
console.log('hello world3')
await next()
console.log('hello world4')
})
// so easy!!! 我们用async await 将异步转化成同步的 是不是就和上面一样简单了
为什么要用async await
中间件默认返回一个Promise
app.use((ctx, next) => {
const a = await next()
console.log(a)
})
app.use((ctx, next) => {
next()
})
// output: Promise { undefined }
// 这里a 值为undefined 的Promise,我们第二个中间件没显式返回嘛
这样改造下
app.use((ctx, next) => {
const a = await next()
console.log(a)
})
app.use((ctx, next) => {
next()
return 'hello world'
})
// output: Promise { 'hello world' }
这样,我们算完全理解了,中间件和洋葱模型了。
最后附上 传说的 洋葱图