- 作者:老汪软件技巧
- 发表时间:2024-09-05 04:01
- 浏览量:
koa是什么
Koa是一个用于构建Web应用和API的轻量级、模块化的Node.js框架。它帮助开发者通过async函数更好地错误处理和更清晰地组织代码。Koa 的中间件机制采用了一种被称为“洋葱模型”的设计模式。
洋葱模型是什么
Koa的洋葱模型是指其中间件的执行方式。
举个例子,结果为1342
当中间件执行到一定程度,调用next,就会进入下一个中间件的执行,当下一个中间件执行完毕然后再回到上一个中间件执行next后的部分,是不是有递归的感觉了?
const Koa = require('koa');
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(8000, () => {
console.log(`Server is starting in 8000`);
});
当一个请求进入时,它会依次穿过每一层中间件(从外到内),每层中间件都可以做一些预处理(如日志记录、身份验证等)。当达到最内部的中间件时,开始处理实际的业务逻辑,之后再通过调用next()方法逐层返回(从内到外),在返回的过程中可以进行响应的构造(如设置响应头、发送响应体等)。
koa结合async、await方式,帮助开发者通过async函数更好地错误处理和更清晰地组织代码。利用这种方式和洋葱模型,我们可以做什么?
app.use(async(ctx, next) => {
const start = new Date();
await next();
const delta = new Date() - start;
console.log (`请求耗时: ${delta} MS`);
console.log('拿到上一次请求的结果:', ctx.state.baiduHTML);
})
app.use(async(ctx, next) => {
// 处理 db 或者进行 HTTP 请求
ctx.state.baiduHTML = await axios.get('http://baidu.com');
})
koa洋葱模型是怎么实现的?use方法
从上面的例子,我们能看到,每个组件,都被我们use、use...,事实上use就是维护了一个middleware中间件数组
use(fn) {
// ...
// 维护中间件数组——middleware
this.middleware.push(fn);
return this;
}
内部实现
listen方法就不多介绍了,事实上就是node中的http模块createServer创建服务,他接收回调函数callback
const Koa = require('koa');
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(8000, () => {
console.log(`Server is starting in 8000`);
});
内部实现,其中compose函数就是洋葱模型的关键
listen(...args) {
debug('listen');
// node http 创建一个服务
const server = http.createServer(this.callback());
return server.listen(...args);
}
callback() {
// 返回值是一个函数
const fn = compose(this.middleware);
const handleRequest = (req, res) => {
// 创建 ctx 上下文环境
const ctx = this.createContext(req, res);
return this.handleRequest(ctx, fn);
};
return handleRequest;
}
因此我们接下来来看看,compose函数是怎么实现的
compose函数
理解了洋葱模型,我们就来看看,use维护了我们的middleware数组,然后conpose是如何将数组中的函数执行掉,并且顺序是135642的
// 实现koa的洋葱模型
// 中间件的执行,执行到一定程度调用next然后就会进入到下一个中间件的执行,一定程度执行next
// 又进入下一个中间件的执行,这个中间件的执行完毕然后回到上一个中间件的执行,上个中间件的执行完毕
// 再往上回,筷子穿洋葱的过程
let middleware = []
middleware.push((ctx, next) => {
console.log(1);
next()
console.log(2);
})
middleware.push((ctx, next) => {
console.log(3);
next()
console.log(4);
})
middleware.push((ctx, next) => {
console.log(5);
next()
console.log(6);
})
let fn = compose(middleware)
fn() // 1 3 5 6 4 2
function compose(middleware) {
return function fn(context, next) {
return dispatch(0)
function dispatch(i) {
if (i > middleware.length - 1) return
let fn = middleware[i] // 取第一个函数
if (i === middleware.length) fn = next //
const nextFn = dispatch.bind(context, i + 1) // 取第二个函数
const p = fn(context, nextFn)
return p
}
}
}
// 1. 递归
// 2. 函数执行到next时要让下一个函数触发