
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 /><a name="ooc8Q"></a>### next返回值next的返回值,会被强制的包装成 Promise- 如果不用 async,可以通过 result.then来获取 Promise的返回值,这样的写法很啰嗦- 如何直接获取 Promise的值,就用 await- 如果用 await就必须用 async,所以,推荐中间件都用 async & await推荐 next都返回 Promise```jsxapp.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之后的代码,说明后面的中间件都执行完成了
 
