什么是洋葱模型
简单来说,就是再不改变原有方法的情况下,在该方法的外侧增加钩子函数,以达到提前拦截与增强输出的效果。
一般中间件都是以洋葱模型的构建方式实现的,例如常用的 node 中的 koa 框架、请求插件 axios 中的 request、response 拦截器等。
为什么使用洋葱模型
以 axios.post 发送post请求为例:
-
首先进入
axios.interceptors.request的拦截器中,添加headers参数,处理请求数据。 -
执行
axios.post方法 -
请求成功后获取响应,并在
axios.interceptors.response拦截器中处理响应数据 -
将处理好的数据,通过
Promise的方式发送到订阅数据的地方。
我们一般处理请求时就是按照上面这个思路来。从上面的例子我们可以看出,我们可以不修改原函数的情况下,轻松处理异步调用顺序、增强原函数的输入输出。
用尾递归实现一个洋葱模型
const m1 = (ctx, next) => {
ctx.req.user = null;
console.log('中间件1 进入', ctx.req);
next()
console.log('中间件1 退出', ctx.req);
}
const m2 = (ctx, next) => {
ctx.req.user = { id: 1 };
console.log('中间件2 进入');
next()
console.log('中间件2 退出');
}
const m3 = () => {
console.log('中间件3');
}
const middlewares = [m1, m2, m3];
const context = { req: {}, res: {} };
let index = 0
function next(i) {
if (index >= middlewares.length) return
let middleware;
while(index < middlewares.length) {
middleware = middlewares[index++]
middleware(context, next)
}
}
next();