开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 24 天,点击查看活动详情
原文来自 我的个人博客
1. Koa 的基本使用
1.1 认识 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+行,是一个更加轻量级的框架;- 我们可以根据需要安装和使用中间件;
下面我们就先来体验一下用 koa 的`Web服务器,创建一个接口。
1.2 Koa 初体验
既然我们要用 koa,那么第一步就需要先安装一下 koa
- 新建一个文件夹,在该文件夹下执行以下
npm i koa
- 编写 js 文件
const Koa = require("koa");
const app = new Koa();
app.use((ctx, next) => {
console.log("中间件 1");
next();
});
app.use((ctx, next) => {
console.log("中间件 2");
ctx.response.body = "Hello World0";
});
app.listen(8000, () => {
console.log("服务器在8000端口启动成功~");
});
- 通过
node执行该文件,访问localhost:8000
在上面的代码中,koa 注册的中间件提供了两个参数:
ctx:上下文(Context)对象koa并没有像express一样,将req和res分开,而是将它们作为ctx的属性;ctx代表一次请求的上下文对象;ctx.request:获取请求对象;ctx.response:获取响应对象;
next:本质上是一个dispatch,类似于express中的next;
1.3 Koa 中间件
koa 通过创建的 app 对象,注册中间件只能通过 use 方法:
koa并没有提供methods的方式来注册中间件;- 也没有提供
path中间件来匹配路径;
在真实开发中,我们可以通过以下方法将路径和 method 分离
- 根据
request自己来判断 - 使用第三方路由中间件
app.use((ctx, next) => {
if(ctx.request.path === '/users') {
if(ctx.request.method === 'POST') {
ctx.response.body = 'Create User Success~'
} else {
ctx.response.body = 'Users List~'
}
} else {
ctx.response.body = 'Other Request Response'
}
})
1.4 路由的使用
koa 官方并没有给我们提供路由的库,我们可以选择第三方库:koa-router
- 安装
koa-router
npm i @koa/router
- 我们可以先封装一个
users/router.js文件
const KoaRouter = require("@koa/router");
const userRouter = new KoaRouter({ prefix: "/users" });
userRouter.get("/", (ctx, next) => {
ctx.body = "用户列表~";
});
userRouter.post("/", (ctx, next) => {
ctx.status = 201;
ctx.body = "用户创建~";
});
module.exports = userRouter;
- 在
index.js中将router.routes()注册为中间件
const userRouter = require("./user/router.js");
const Koa = require("koa");
const app = new Koa();
app.use(userRouter.routes());
app.use(userRouter.allowedMethods());
app.listen(8000, () => {
console.log("服务器在8000端口启动成功~");
});
- 运行
index.js文件即可启动服务
注意:allowedMethods 用于判断某一个 method 是否支持:
- 如果我们请求
get,那么是正常的请求,因为我们有实现 get; - 如果我们请求
put、delete、patch,那么就自动报错:Method Not Allowed,状态码:405; - 如果我们请求
link、copy、lock,那么久自动报错:NotImplemented,状态码:501;
2. 参数解析
koa 的参数解析与 express 比较相似的只是有些细微的差别
2.1 解析参数:params & query
请求地址:http://localhost:8000/users/123
获取 params:
const userRouter = new Router({prefix: "/users"})
userRouter.get("/:id", (ctx, next) => {
console.log(ctx.params.id)
ctx.body = "Hello World"
})
请求地址:http://localhost:8000/users/login?username=zhangsan&password=123
获取 query:
userRouter.get("/login", (ctx, next) => {
console.log(ctx.request.query);
ctx.body = "Hello Wolrd";
});
2.2 解析参数:json
请求地址:http://localhost:8000/login
body 是 json 格式:
{
username: "zhangsan",
password: "lisi"
}
获取 json 数据:
- 安装依赖
npm install koa-bodyparser
- 使用
koa-bodyparser的中间件
const bodyParser = require('koa-bodyparser')
app.use(bodyParser())
userRouter.post("/login", (ctx, next) => {
console.log(ctx.request.body);
ctx.status = 201;
ctx.body = "用户创建~";
});
2.3 解析参数:x-www-form-urlencoded
请求地址:http://localhost:8000/login
body 是 x-www-form-urlencoded 格式:
获取 json 数据:(和 json 是一致的)
const bodyParser = require('koa-bodyparser')
app.use(bodyParser())
app.use((ctx,next) => {
console.log(ctx.request.body)
ctx.body = "Hello World"
})
2.4 解析参数 form-data
请求地址:http://localhost:8000/login
body 是 form-data 格式
解析 body 中的数据,我们需要使用 multer
- 安装依赖
npm install koa-multer
- 使用
multer中间件;
const multer = require("koa-multer");
const upload = multer({});
app.use(upload.any());
app.use((ctx, next) => {
console.log(ctx.req.body);
});
2.5 Multer 上传文件
const path = require("path");
const Router = require("@koa/router");
const multer = require("koa-multer");
const Koa = require("koa");
const app = new Koa();
const upload = multer({
storage: multer.diskStorage({
destination: (req, file, cb) => {
cb(null, "./uploads/");
},
filename: (req, file, cb) => {
cb(null, Date.now() + path.extname(file.originalname));
},
}),
});
const fileRouter = new Router();
fileRouter.post("/upload", upload.single("avatar"), (ctx, nexy) => {
console.log(ctx.req.file);
ctx.body = "上传成功";
});
app.use(fileRouter.routes());
app.listen(8000, () => {
console.log("服务器在8000端口启动成功~");
});
启动服务,在postman中上传一张图片
可以看到服务端已经存储了一张图片
2.6 静态服务器
koa 并没有内置部署相关的功能,所以我们需要使用第三方库
npm install koa-static
部署的过程类似于 express:
const Koa = require('koa')
const static = require('koa-static')
const app = new Koa()
app.use(static('./build'))
app.use(8000, () => {
console.log('静态服务器启动成功')
})
2.7 数据的相应
输出结果:body将响应主体设置为以下之一:
- string :字符串数据
- Buffer :Buffer数据
- Stream :流数据
- Object|| Array:对象或者数组
- null :不输出任何内容
ctx.body = ['1','2','3']
// 或
ctx.response.body = {username: 'zhangsan', password: 'lisi'}
如果 response.status 尚未设置,Koa 会自动将状态设置为 200 或 204 。
- 请求状态:
status
ctx.status = 201
// 或者
ctx.response.status = 204
2.8 错误处理
const Koa = requrie('koa')
const app = new Koa()
app.use((ctx,next) => {
ctx.app.emit('error', new Error('哈哈哈'), ctx)
})
app.on('error', (err, ctx) => {
console.log(err.message)
ctx.response.body = '哈哈哈'
})
app.listen(8000, () => {
console.log('错误处理服务器启动成功~')
})