写在前面
大家好,我是一溪风月🌸,一名前端程序员,上篇文章我们学习了Express框架,这篇文章我们将学习和讲解Koa框架,事实上,Koa是Express同一个团队开发的一个新的Web框架,目前团队的核心开发者TJ的主要精力也在维护Koa,express已经交给团队维护了,Koa旨在为Web应用程序和API提供更小,更丰富和更强大的能力,相对于Express具有更强的异步处理能力,Koa的核心代码只有1600+行,是一个更加轻量的框架,我们可以根据需要安装和使用中间件,好了,让我们开始吧!
一.Koa初体验
首先我们像使用Express一样,来体验一下koa的Web服务器,Koa也是通过注册中间件来完成请求操作的,Koa注册的中间件提供了两个参数,参数分别如下:
ctx:上下文(Context)对象;
- koa并没有像express一样,将req和res分开,而是将它们作为ctx的属性。
- ctx代表一次请求的上下文对象。
ctx.request
:获取请求的对象。ctx.response
:获取响应对象。
next:本质上是一个dispatch,类似于之前的next;
js
const Koa = require("koa")
// 创建app对象
const app = new Koa()
// 注册中间件(middleware)
// koa的中间件有两个参数:ctx/next
app.use((ctx, next) => {
// 1.请求对象
console.log(ctx.request) // 请求对象:Koa封装的请求对象
console.log(ctx.req) // 请求对象:Node封装的请求对象
// 2.响应对象
console.log(ctx.response)
console.log(ctx.res)
// 3.其他属性
console.log(ctx.query)
})
app.listen(6000, () => {
console.log("服务启动在6000端口🚀")
})
二.Koa中间件
我们使用Koa创建的应用,注册中间件只能通过use
方法,因为Koa并没有提供methods的方式来注册中间件,也没有提供path中间件来匹配路径,但是真实开发中我们需要将路径和method分离,在Koa中我们可以使用如下两种方式。
- 方式一:根据request自己来判断。
- 方式二:使用第三方路由中间件。
如果我们在开发中不使用路由中间件来开发,我们需要像如下这种方式来判断路由进行匹配不同的接口。
js
app.use((ctx, next) => {
if (ctx.path === '/users') {
if (ctx.method === 'GET') {
ctx.body = "user data list"
} else if (ctx.method === 'POST') {
ctx.body = "create user success~"
}
} else if (ctx.path === '/home') {
ctx.body = "home data list~"
} else if (ctx.path === '/login') {
ctx.body = "登录成功,欢迎回来~"
}
})
是不是看起来挺乱的,代码可读性和可维护性并不好,所以一般我们会使用路由库来做这些操作。
三.路由的使用
koa官方并没有给我们提供路由的库,我们可以选择第三方库:koa-router
js
npm install @koa/router
然后我们就可以使用路由来完成上述路径和方法的匹配操作。
js
const Koa = require("koa")
const koaRouter = require('@koa/router')
// 创建服务器app
const app = new Koa()
// 创建一个路由对象
const userRouter = new koaRouter({ prefix: '/users' })
userRouter.get('/', (ctx, next) => {
ctx.body = "user list data"
})
userRouter.get('/:id', (ctx, next) => {
const id = ctx.params.id
ctx.body = '获取了用户' + id
})
userRouter.post('/', (ctx, next) => { })
userRouter.delete('/:id', (ctx, next) => {
const id = ctx.params.id
ctx.body = '删除了用户的' + id
})
userRouter.patch('/:id', (ctx, next) => {
const id = ctx.params.id
ctx.body = '获取了用户的' + id
})
// 让路由中间件生效
app.use(userRouter.routes())
app.use(userRouter.allowedMethods())
// 启动服务器
app.listen(6000, () => {
console.log("服务启动在6000端口🚀")
})
其中allowedMethods
的作用是当我们请求一个不存在的方法的时候服务端会返回如下的内容:

- 如果我们请求get,那么请求是正常的,因为我们有实现get。
- 如果我们请求put,delete,patch,那么就会自动报错:Method Not Allowed 状态码405
- 如果我们请求link,copy,lock那么就会自动报错,Not Implemented,状态码501
四.参数解析:params-query
例如我们的请求地址是 :http://localhost:8000/users/123 然后我们来获取params
js
// 注册路由对象
const useRouter = new KoaRouter({ prefix: '/users' })
// 1.params
useRouter.get('/:id', (ctx, next) => {
const id = ctx.params.id
ctx.body = "user list data" + id
})
然后我们对query做解析,比如我们的地址是:http://localhost:8000/login?username=why&password=123
js
useRouter.get('/', (ctx, next) => {
const query = ctx.query
ctx.body = '用户的query数据' + JSON.stringify(query)
})
五.参数解析:json
比如当我们的请求地址为:http://localhost:8000/login body是json格式:
js
{
"username":"coderwhy",
"password":13,
}
当在Koa中需要对请求体中的数据进行解析的时候不能直接通过ctx.body
或者ctx.request.body
进行获取,我们一般会使用第三方插件koa-bodyparser
来进行解析,我们可以按照如下进行安装。
js
npm install koa-bodyparser
然后我们在我们的app文件中使用一下,就可以解析json格式的数据了。
js
// 使用第三方中间件
app.use(bodyParser())
// 注册路由对象
const useRouter = new KoaRouter({ prefix: '/users' })
useRouter.post('/json', (ctx, next) => {
const json = ctx.request.body
ctx.body = JSON.stringify(json)
})
六.参数解析:x-www-form-urlencoded
在上面我们解析了json格式的请求数据,那么接下来我们来解析一下x-www-form-urlencoded
格式的数据,我们假定我们的请求地址如下:http://localhost:8000/login 请求体的格式是x-www-form-urlencoded

js
useRouter.post('/urlencoded', (ctx, next) => {
console.log(ctx.request.body)
ctx.body = "urlencoded"
})
对于urlencoded
的解析json的中间件依然是适用的,所以我们可以直接进行解析完成,并不需要另外安装其他的中间件来完成上述任务。
七.参数解析:form-data
接下来我们来解析一下form-data
格式的数据,我们假设请求地址为:http://localhost:8000/login body是form-data的格式,对于form-data的格式数据我们需要安装另外一个第三方中间件来解析
js
npm install koa-multer

然后我们编写一下代码
js
const koaMulter = require("koa-multer")
const upload = koaMulter({})
app.use(upload.any())
useRouter.post('/form-data', (ctx, next) => {
console.log(ctx.req.body)
ctx.body = "form-data"
})
八.Multer文件上传
我们在上述内容中了解了Koa框架中如何进行文件的上传,首先我们先实现一下单个文件的上传
js
const koaMulter = require("koa-multer")
const upload = koaMulter({
storage:koaMulter.diskStorage({
destination(req,file,cb){
cb(null,'./uploads')
},
filename(req,file,cb){
cb(null,Date.now()+'_'+file.originalname)
}
})
})
// 文件上传
useRouter.post('/avatar', upload.single('avatar'), (ctx, next) => {
ctx.body = "user list data~"
})

然后我们就可以看到文件被正常的上传上去了,其实如果我们不定义图片的后缀也是没有问题的一般情况下图片的后缀不会影响图片的编码,然后我们再来实现下多文件的上传。
js
useRouter.post('/photos', upload.array('photos'), (ctx, next) => {
ctx.body = "more data uploads"
})
九.静态服务器
我们在Express中搭建静态服务器可以直接使用Express内置的相关功能来直接部署静态资源,但是不同的是Koa并没有给我们内置静态资源服务器,我们想要部署我们的静态资源的话我们需要进行使用第三方库,首先我们需要安装以下这个第三方库。
js
npm install koa-static
在Koa中部署静态资源的方式和在Express中部署静态资源非常的类似。
js
const Koa = require("koa")
const static = require("koa-static")
const app = new Koa()
app.use(static('/uploads'))
app.listen(6000, () => {
console.log("服务启动在6000端口~")
})
十.数据响应
输出结果:body将响应主题设置为以下之一
- string : 字符串数据
- Buffer:Buffer数据
- Stream:流数据
- Object || Array :对象或者数组
- null:不输出任何内容
- 如果response.status尚未设置,Koa会自动将状态设置为200或者204
js
const Koa = require("koa")
const KoaRouter = require("@koa/router")
const fs = require("fs")
const app = new Koa()
const userRouter = new KoaRouter({ prefix: '/users' })
// string
userRouter.get('/string', (ctx, next) => {
ctx.body = "你好世界~"
})
// buffer
userRouter.get('/buffer', (ctx, next) => {
ctx.body = Buffer.from("你好世界~")
})
// stream
userRouter.get('/stream', (ctx, next) => {
const readStream = fs.createReadStream("./uploads/1744290334979_js.png")
ctx.type = "image/jpg"
ctx.body = readStream
})
// array/object
userRouter.get("/array", (ctx, next) => {
ctx.body = ['a', 'b', 'c']
})
// null
userRouter.get('/null', (ctx, next) => {
ctx.body = null // 为null会自动设置为204
})
app.use(userRouter.routes())
app.use(userRouter.allowedMethods())
app.listen(6000, () => {
console.log("服务器启动在6000端口~")
})
十一.错误的处理
在Koa中我们也可以像在Express中一样进行全局的错误处理,接下来我们可以看下如何在Koa中进行错误处理。
js
app.use((ctx, next) => {
ctx.app.emit('error', new Error('哈哈哈'), ctx)
})
app.on('error', (err, ctx) => {
console.log(err.message)
ctx.response.body = "哈哈哈"
})
十二.总结
这篇文章到这里就结束了🌸,这篇文章我们大概讲解了一下Koa的使用方式,以及大致了解了Koa和Express之间的区别,Koa的特点是比较轻量,基本上所有的东西都需要通过第三方插件来解决,但是Koa也有自己更加强大的地方,在后续我们详细了解Koa和Express之间的区别的时候再交流学习。