一、认识Koa
前面我们已经学习了express,另外一个非常流行的Node Web服务器框架就是Koa。
Koa官方的介绍:
- koa:next generation web framework for node.js;
- koa:node.js的下一代web框架;
koa是express同一个团队开发的一个新的Web框架:
- 目前团队的核心开发者TJ的主要精力也在维护Koa,express已经交给团队维护了;
- Koa旨在为Web应用程序和API提供更小、更丰富和更强大的能力;
- 相对于express具有更强的异步处理能力(后续我们再对比);
- Koa的核心代码只有1600+行,是一个更加轻量级的框架,我们可以根据需要安装和使用中间件;
学习了express之后,学习koa的过程是很简单的;
二、Koa初体验
npm init -y
npm i koa
1 2 3 4 5 6 7 8 9 10 11
| const Koa = require('koa');
const app = new Koa()
app.listen(8000,() => { console.log('服务器启动成功'); })
|
没有返回数据
1.在原生http中 和 express中,客户端会一直请求,所以一般设置超时时间
2.但在koa中,执行完所有的中间件没有返回数据时,会返回Not Found页面
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| const Koa = require('koa');
const app = new Koa();
app.use((ctx, next) => { ctx.response.body = 'Hello'; next(); }); app.listen(8000, () => { console.log('服务器启动成功'); });
|
koa注册的中间件提供了两个参数:
三、Koa中间件
koa通过创建的app对象,注册中间件只能通过use方法:
Koa并没有提供methods的方式来注册中间件;
也没有提供path中间件来匹配路径;
但是真实开发中我们如何将路径和method分离呢?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| const Koa = require('koa');
const app = new Koa(); app.use((ctx, next) => { if (ctx.request.url === '/login') { if (ctx.request.method === 'POST') { ctx.response.body = 'login success'; } } else { ctx.response.body = 'Hello'; } }); app.listen(8000, () => { console.log('服务器启动成功'); });
|
- 方式二:使用第三方路由中间件;
- koa官方并没有给我们提供路由的库,我们可以选择第三方库:koa-router
- npm install koa-router
- 我们可以先封装一个 user.router.js 的文件:
- 在app中将router.routes()注册为中间件:
users.js:
1 2 3 4 5 6 7 8 9 10 11
| const Koa = require('koa'); const Router = require('koa-router');
const router = new Router({ prefix: '/users' }); router.get('/', (ctx, next) => { ctx.response.body = 'get request'; }); router.put('/', (ctx, next) => { ctx.response.body = 'put request'; }); module.exports = router;
|
Koa路由使用.js
1 2 3 4 5 6 7 8 9 10 11
| const Koa = require('koa'); const app = new Koa(); const userRouter = require('./routes/users.js');
app.use(userRouter.routes())
app.use(userRouter.allowedMethods()) app.listen(8000, () => { console.log('服务器启动成功'); });
|
- 注意:allowedMethods用于判断某一个method是否支持:
- 如果请求 get,那么是正常的请求,因为我们有实现get;
- 如果请求 put、delete、patch,那么就自动报错:Method Not Allowed,状态码:405;
- 如果请求 link、copy、lock,那么久自动报错:Not Implemented,状态码:501
四、参数解析
params — query
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| const Koa = require('koa'); const Router = require('koa-router'); const app = new Koa();
const router = new Router({ prefix: '/users' });
app.use((ctx, next) => { console.log(ctx.request.url); console.log(ctx.request.params); console.log(ctx.request.query); }); app.listen(8000, () => { console.log('服务器启动成功'); });
|
这样是拿不到params
需要在路由里定义,才能拿到:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| const Koa = require('koa'); const Router = require('koa-router'); const app = new Koa(); const router = new Router({ prefix: '/users' });
router.get('/:id', (ctx, next) => { console.log(ctx.request.params); console.log(ctx.request.query); ctx.response.body = 'get request'; });
app.use(router.routes()); app.listen(8000, () => { console.log('服务器启动成功'); });
|
post请求,参数为json格式
1 2 3 4
| { "title":"pc", "price":"12345" }
|
正常ctx.request.body是拿不到数据的,需要第三方库bodyparser
npm install koa-bodyparser
1 2 3 4 5 6 7 8 9 10 11 12
| const Koa = require('koa'); const bodyparser = require('koa-bodyparser'); const app = new Koa(); app.use(bodyparser()); app.use((ctx, next) => { console.log(ctx.request.body); });
app.listen(8000, () => { console.log('服务器启动成功'); });
|
post请求,参数为x-www-form-urlencoded格式

1 2 3 4 5 6 7 8 9 10 11 12 13
| const Koa = require('koa'); const bodyparser = require('koa-bodyparser'); const app = new Koa(); app.use(bodyparser()); app.use((ctx, next) => { console.log(ctx.request.body); });
app.listen(8000, () => { console.log('服务器启动成功'); });
|
解析body中的数据,我们需要使用multer
安装依赖:npm install koa-multer;
使用 multer中间件;

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| const Koa = require('koa'); const multer = require('koa-multer'); const app = new Koa(); const upload = multer() app.use(upload.any()); app.use((ctx, next) => { console.log(ctx.req.body); });
app.listen(8000, () => { console.log('服务器启动成功'); });
|
上传文件
参考express。
五、数据响应
body将响应主体设置为以下之一:
- string :字符串数据
- Buffer :Buffer数据
- Stream :流数据
- Object|| Array:对象或者数组
- null :不输出任何内容
- 如果response.status尚未设置,Koa会自动将状态设置为200或204。
请求状态:status
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| const Koa = require('koa'); const multer = require('koa-multer'); const app = new Koa(); const upload = multer() app.use(upload.any()); app.use((ctx, next) => { console.log(ctx.req.body); });
app.listen(8000, () => { console.log('服务器启动成功'); });
|
六、静态服务器
koa并没有内置部署相关的功能,所以我们需要使用第三方库:
部署的过程类似于express:
1 2 3 4 5 6 7 8 9 10
| const Koa = require('koa'); const static = require('koa-static') const app = new Koa();
app.use(static('静态文件根目录'))
app.listen(8000, () => { console.log('服务器启动成功'); });
|
七、错误处理
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| const Koa = require('koa');
const app = new Koa();
app.use((ctx, next) => { const isLogin = false; if (!isLogin) { ctx.app.emit('error', new Error('您还没有登录'), ctx); } }); app.on('error', (err, ctx) => { ctx.status = 401; ctx.body = err.message; });
app.listen(8000, () => { console.log('服务器启动成功'); });
|
ctx.body 其实是ctx.response.body做了一层代理。
但不是所以方法都做了代理。
八、Koa和express对比
从架构设计上来说:
- express是完整和强大的,其中帮助我们内置了非常多好用的功能;
- koa是简洁和自由的,它只包含最核心的功能,并不会对我们使用其他中间件进行任何的限制。
- 甚至是在app中连最基本的get、post都没有给我们提供;
- 我们需要通过自己或者路由来判断请求方式或者其他功能;
因为express和koa框架他们的核心其实都是中间件:
但是他们的中间件事实上,它们的中间件的执行机制是不同的,特别是针对某个中间件中包含异步操作时;
同步时:
- 调用next后调用res.end(),res.end会等所有next都执行完在返回
异步时:
- next中有异步操作,不会等异步的结果,直接执行res.end()
- 但是koa返回的是promise对象,可以使用async await加以控制