1. Koa 特点
1.1 更好的处理异步
Koa 的核心设计是基于 async/await 异步编程模型。这使得 Koa 可以更好地处理异步操作,相比于传统的回调方式,代码更清晰且更易于维护。
1.2 无内置中间件
与 Express 不同,Koa 并没有内置任何中间件,如路由、模板引擎等。Koa 提供了一个极简的核心,可以根据自己的需求添加中间件(插件)。
1.3 洋葱模型中间件
Koa 中的中间件采用了“洋葱模型”,这意味着请求通过一系列中间件层的方式处理,每个中间件都可以在请求向下传递之前做一些事情,并且在响应返回时再做处理。这种结构非常适合处理日志记录、权限验证、错误处理等情况。
并且由于洋葱模型和异步的优化,解决了 express 潜在的异步问题。
const Koa = require('koa');
const app = new Koa();// Logger 中间件
app.use(async (ctx, next) => {console.log(`${ctx.method} ${ctx.url}`);await next(); // 传递到下一个中间件
});// 响应中间件
app.use(async ctx => {ctx.body = 'Hello Koa';
});app.listen(3000);
console.log('Server running on http://localhost:3000');
express 潜在的回调问题:
而如果使用 koa,则会正常输出 1,2,3,4 ,主要原因是对于 async await 的支持。
可以看到,对于每个中间件,在完成了一些事情后,可以非常优雅的将控制权传递给下一个中间件,并能够等待它完成,当后续的中间件完成处理后,控制权又回到了自己,这种中间件模型称之为洋葱模型。
2. 核心概念
2.1 Context (ctx
)
Koa 中的每个 HTTP 请求都会生成一个 Context
对象,简称 ctx
。ctx
对象整合了 request
和 response
(为原生 req, res 的二次封装),开发者可以通过 ctx
来读取请求信息和设置响应数据。
ctx.request
: 处理请求的详细信息,如请求头、请求体、查询参数等。ctx.response
: 处理响应的详细信息,如状态码、响应头、响应体等。
app.use(async ctx => {ctx.body = 'This is the response body'; // 设置响应内容ctx.status = 200; // 设置响应状态码
});
为了方便使用,Koa将request和response中的很多成员提取到了context中,并使用访问器控制。
2.2 中间件
Koa 的中间件是一个 async
函数,可以使用 await next()
来控制请求传递给下一个中间件。由于采用了 async/await,错误处理可以使用标准的 try/catch
结构。
app.use(async (ctx, next) => {try {await next(); // 调用下一个中间件} catch (err) {ctx.status = err.status || 500;ctx.body = 'Internal Server Error';console.error('Error occurred:', err);}
});
2.3 错误处理
Koa 提供了内置的错误处理机制,可以在中间件中捕获错误。由于 Koa 主要基于 async/await
,你可以轻松地用 try/catch
捕获异步代码中的异常。
app.use(async (ctx, next) => {try {await next();} catch (err) {ctx.status = err.status || 500;ctx.body = 'Something went wrong';}
});
koa 内部也提供了错误的注册:
// 注册
app.on("error", function(e) { console.log(e) } )
// 使用
app.use(function(ctx, next) {// ...ctx.throw(403, "you have no permission");next();
})
2.3 API
见文档,都写的非常清楚。Koa API
2.4 cookie
2.5 自定义空间
有时,某些中间件希望添加一些额外的信息,以方便后续中间件处理,比如当前登录的用户信息。
Koa建议把这些信息添加到ctx.state中该属性默认是一个空对象,专门提供给中间件开发者添加额外信息的。
3. 常见中间件
虽然 Koa 本身没有内置路由或其他功能,但有很多第三方中间件可用:
3.1 路由 (koa-router
)
Koa 官方推荐使用 koa-router
来处理路由。
const Koa = require('koa');
const Router = require('@koa/router');
const app = new Koa();
const router = new Router();router.get('/', ctx => {ctx.body = 'Hello World!';
});app.use(router.routes());
app.listen(3000);
3.2 静态文件服务 (koa-static
)
可以使用 koa-static
来提供静态文件服务,比如 CSS、JS 文件等。
const serve = require('koa-static');
app.use(serve('./public'));
3.3 请求体解析 (koa-bodyparser
)
要处理 POST 请求中的表单或 JSON 数据,可以使用 koa-bodyparser
。
const bodyParser = require('koa-bodyparser');
app.use(bodyParser());app.use(async ctx => {console.log(ctx.request.body); // 获取 POST 请求的 body 数据ctx.body = 'Data received';
});
4. Koa 与 Express 的对比
- 中间件处理: Koa 中间件基于 async/await,Express 依赖回调。
- 灵活性: Koa 没有内置的路由或静态文件服务,需要通过第三方库添加;Express 则自带这些功能。
- 上下文对象: Koa 使用
ctx
对象统一处理请求和响应,而 Express 分别使用原生的req
和res
。
express:
koa: