什么是Koa?
Koa是一个精简的node
框架,被认为是第二代Node
框架,其最大的特点就是独特的中间件流程控制,是一个典型的洋葱模型,它的核心工作包括下面两个方面:
- 将
node
原生的req
和res
封装成为一个context
对象。 - 基于
async/await
的中间件洋葱模型机制。
什么是洋葱模型。
Koa
的洋葱模型是以next
()函数为分割点,先由外到内执行Request
的逻辑,然后再由内到外执行Response
的逻辑,这里的request
的逻辑,我们可以理解为是next
之前的内容,response
的逻辑是next
函数之后的内容,也可以说每一个中间件都有两次处理时机。洋葱模型的核心原理主要是借助compose
方法
为什么需要洋葱模型?
因为很多时候,在一个app
里面有很多中间件,有些中间件需要依赖其他中间件的结果,用葱模型可以保证执行顺序,如果没有洋葱模型,执行顺序可能出乎我们的预期
如下是洋葱代码的案例:
const Koa = require('koa');
//Applications
const app = new Koa();
// 中间件1
app.use((ctx, next) => {
console.log(1);
next();
console.log(2);
});
// 中间件 2
app.use((ctx, next) => {
console.log(3);
next();
console.log(4);
});
app.listen(7000, '0.0.0.0', () => {
console.log(`Server is starting`);
});
// 中间件的打印顺序是1 -> 3 -> 4 -> 2
总结
Koa
的洋葱模型指的是以 next
() 函数为分割点,先由外到内执行 Request
的逻辑,再由内到外执行 Response
的逻辑。通过洋葱模型,将多个中间件之间通信等变得更加可行和简单。其实现的原理并不是很复杂,主要是 compose
方法。
简易版 compose
模范 koa
的逻辑,我们可以写一个简易版的 compose
。方便大家的理解:
const middleware = []
let mw1 = async function (ctx, next) {
console.log("next前,第一个中间件")
await next()
console.log("next后,第一个中间件")
}
let mw2 = async function (ctx, next) {
console.log("next前,第二个中间件")
await next()
console.log("next后,第二个中间件")
}
let mw3 = async function (ctx, next) {
console.log("第三个中间件,没有next了")
}
function use(mw) {
middleware.push(mw);
}
function compose(middleware) {
return (ctx, next) => {
return dispatch(0);
function dispatch(i) {
const fn = middleware[i];
if (!fn) return;
return fn(ctx, dispatch.bind(null, i+1));
}
}
}
use(mw1);
use(mw2);
use(mw3);
const fn = compose(middleware);
fn();