eggjs洋葱圈模型
config/config.default.js里面不需要引入 middleware,直接写中间件的名字
config.middleware = ['m1', 'm2', 'm3']
// 中间件的 options参数
config.m1 = { title: 'middlware1', type: 'chart' }
middleware里面如果没有 next,页面会显示 404
必须的一步, await next()
middleware
app/middleware/m1.js
module.exports = options => {
return async (ctx, next) => {
console.log(ctx);
await next();
}
}
- options 中间件的配置参数
- ctx 当前的上下文
- next 下一个中间件
koa洋葱圈模型
const Koa = require('koa');
const app = new Koa(); // 应用程序对象
function getUesr(ctx, next) {}
app.use(getUser);
app.use((ctx, next) => {
console.log(10);
next();
console.log(20);
})
app.use((ctx, next) => {
console.log(30);
next();
console.log(40);
})
- console顺序 10 -> 30 -> 40 -> 20
- 先执行第一个中间件,打印 10, 然后执行第二个中间件,打印 30
async & awit
异步编程,async & await 洋葱模型
如果不加上 async await,不能保证所有中间件都是按照洋葱模型来执行的
- next() 返回一定是 Promise
- 如果 next() 返回 undefined,那就是第二个中间件没有返回值 ```javascript app.use(async (ctx, next) => { console.log(10); await next(); console.log(20); });
app.use(async (ctx, next) => { console.log(30); await next(); console.log(40); });
强制 Promise<br />异步都用 async & await<br />![image.png](https://cdn.nlark.com/yuque/0/2021/png/112859/1623323816409-3ed2dd73-bd39-4e83-a91b-e5372b8d4ddf.png#clientId=u7e6ba793-bb1a-4&crop=0.0429&crop=0.1339&crop=0.9517&crop=0.8734&from=paste&height=295&id=u5f4bc8d5&margin=%5Bobject%20Object%5D&name=image.png&originHeight=857&originWidth=1556&originalType=binary&ratio=2&rotation=0&showTitle=false&size=85124&status=done&style=none&taskId=u2cf925f7-2fec-4bd3-8f2c-9e250180306&title=&width=535.9957275390625)
<a name="ooc8Q"></a>
### next返回值
next的返回值,会被强制的包装成 Promise
- 如果不用 async,可以通过 result.then来获取 Promise的返回值,这样的写法很啰嗦
- 如何直接获取 Promise的值,就用 await
- 如果用 await就必须用 async,所以,推荐中间件都用 async & await
推荐 next都返回 Promise
```jsx
app.use((ctx, next) => {
console.log(10);
const result = next();
console.log(result);
result.then(res => { console.log(res) });
console.log(200);
});
app.use((ctx, next) => {
console.log(30);
console.log(40);
return 100 // Promise {100}
});
- 执行顺序: 10 -> 30 -> 40 -> Promise {100} -> 200
async
async 会把一个函数包装成一个 Promise;
函数的任意返回值都会被包装成一个 Promise
async function func() {
return 100
}
console.log(func()); // Promise {100}
为什么中间件函数要加上 async?
- 因为中间件函数调用了 await,如果不加 async,直接使用 await会报错
- 其实,中间件函数不加 async,返回的也是 Promise
- 中间件使用 await next() 就是为了保证中间件的洋葱模型,按照顺序执行
- 洋葱模型以 next为分界线
await求值
await直译为等待,会阻塞线程,阻塞当前线程
await也可以求值,后面跟着个表达式,对表达式求值
await可以把一个异步的调用,变成一个同步的调用
await 100 * 200;
对资源的操作,都是异步的
- 读取文件
- 写入文件
- 上传文件
- 发送 http请求
- 操作数据库
一定要保证洋葱圈模型
如果中间件使用 await next,就会阻塞线程,直接进入到下一步;等 await执行完成后,才会执行下面的代码
app.use((ctx, next) => {
console.log(10);
next();
console.log(20);
});
app.use(async (ctx, next) => {
console.log(30);
await next();
console.log(40);
});
执行顺序:10 -> 30 -> 20 -> 40
保证中间件按照洋葱模型执行的条件:
next前面必须使用 await
- 中间件函数执行是有顺序的
- next之前的代码,说明中间件还没执行完成
- next之后的代码,说明后面的中间件都执行完成了