Koa 框架
认识 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 初体验
-
我们来体验一下
koa
的Web
服务器-
在桌面新建文件夹
learn_koa
-
打开终端初始化项目
npm init -y
-
在
package.json
配置脚本{ "name": "learn_koa", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "start": "nodemon ./src/app.js" }, "keywords": [], "author": "", "license": "ISC", "dependencies": { "koa": "^2.13.4", "nodemon": "^2.0.16" } }
-
根据脚本新建文件
src
,在文件src
下面新建文件夹app.js
-
安装
koa
框架npm i koa
-
启动项目
npm start
-
-
koa
注册的中间件提供了两个参数: -
ctx
:上下文(Context
)对象;-
koa
并没有像express
一样,将req
和res
分开,而是将它们作为ctx
的属性; -
ctx
代表依次请求的上下文对象; -
ctx.request
:获取请求对象; -
ctx.response
:获取响应对象;const Koa = require("koa"); const app = new Koa(); // context 上下文对象 // 包含两个主要的对象 request responst app.use((context, next) => { console.log(context); console.log("普通中间件"); }); app.listen(8888, () => { console.log("服务器开启成功"); });
-
-
next
:本质上是一个dispatch
,类似于之前的next
;
Koa中间件
koa
通过创建的app
对象,注册中间件只能通过use
方法:Koa
并没有提供methods
的方式来注册中间件;- 也没有提供
path
中间件来匹配路径;
- 但是真实开发中我们如何将路径和
method
分离呢?- 方式一:根据
request
自己来判断; - 方式二:使用第三方路由中间件;
- 方式一:根据
路由的使用
-
koa
官方并没有给我们提供路由的库,我们可以选择第三方库:koa-router
-
npm install koa-router
-
-
我们可以先封装一个
user.router.js
的文件:// router/user.js const Router = require("koa-router"); const userRouter = new Router({ prefix: "/user", }); userRouter.get("/", (ctx) => { // 响应结果 ctx.body = "用户列表"; }); userRouter.post("/", (ctx) => { // 响应结果 ctx.body = "添加成功"; }); userRouter.delete("/", (ctx) => { // 响应结果 ctx.body = "删除成功"; }); userRouter.patch("/", (ctx) => { // 响应结果 ctx.body = "修改成功"; }); module.exports.userRouter = userRouter;
-
在
app
中将router.routes()
注册为中间件:const Koa = require("koa"); const { userRouter } = require("./router/user"); const app = new Koa(); // 注册路由中间件 // userRouter.routes() 加载路由规则 // userRouter.allowedMethods() 对于没有实现和没有使用的请求方式做出正确的响应 app.use(userRouter.routes()).use(userRouter.allowedMethods()); app.listen(8888, () => { console.log("服务器开启成功"); });
-
注意:
allowedMethods
用于判断某一个method
是否支持:- 如果我们请求
get
,那么是正常的请求,因为我们有实现get
; - 如果我们请求
put
、delete
、patch
,那么就自动报错:Method Not Allowed
,状态码:405
; - 如果我们请求
link
、copy
、lock
,那么就自动报错:Not Implemented
,状态码:501
;
- 如果我们请求
参数解析:params - query
-
请求地址:
localhost:8888/user/2
-
获取
params
:// router/user.js const Router = require("koa-router"); const userRouter = new Router({ prefix: "/user", }); userRouter.get("/:id", (ctx) => { // params 方式传参 console.log(ctx.params.id); // 响应结果 ctx.body = "用户列表"; }); module.exports.userRouter = userRouter;
-
-
请求地址:
localhost:8888/user?name=张三&age=21
-
获取
query
:// router/user.js const Router = require("koa-router"); const userRouter = new Router({ prefix: "/user", }); userRouter.get("/", (ctx) => { // query 方式传参 console.log(ctx.query); // 响应结果 ctx.body = "用户列表"; }); module.exports.userRouter = userRouter;
-
参数解析:json
-
请求地址:
http://localhost:8888/user
-
body
是json
格式
-
-
获取
json
数据: -
安装依赖:
npm install koa-bodyparser
; -
使用
koa-bodyparser
的中间件;-
在入口文件
index.js
中const Koa = require("koa"); const bodyParser = require("koa-bodyparser"); const { userRouter } = require("./router/user"); const app = new Koa(); // bodyParser() 解析 json 数据的中间件 app.use(bodyParser()); // 注册路由中间件 // userRouter.routes() 加载路由规则 // userRouter.allowedMethods() 对于没有实现和没有使用的请求方式做出正确的响应 app.use(userRouter.routes()).use(userRouter.allowedMethods()); app.listen(8888, () => { console.log("服务器开启成功"); });
-
在
router
文件下面的user.js
中// router/user.js const Router = require("koa-router"); const userRouter = new Router({ prefix: "/user", }); userRouter.post("/", (ctx) => { // json 方式传参 console.log(ctx.request.body); // 响应结果 ctx.body = "添加成功"; }); module.exports.userRouter = userRouter;
-
参数解析:x-www-form-urlencoded
-
请求地址:
http://localhost:8888/user
-
body
是x-www-form-urlencoded
格式:
-
-
获取
json
数据:(和json
是一致的)-
安装依赖:
npm install koa-bodyparser
; -
使用
koa-bodyparser
的中间件;-
在入口文件
index.js
中const Koa = require("koa"); const bodyParser = require("koa-bodyparser"); const { userRouter } = require("./router/user"); const app = new Koa(); // bodyParser() 解析 json 数据的中间件 app.use(bodyParser()); // 注册路由中间件 // userRouter.routes() 加载路由规则 // userRouter.allowedMethods() 对于没有实现和没有使用的请求方式做出正确的响应 app.use(userRouter.routes()).use(userRouter.allowedMethods()); app.listen(8888, () => { console.log("服务器开启成功"); });
-
在
router
文件下面的user.js
中// router/user.js const Router = require("koa-router"); const userRouter = new Router({ prefix: "/user", }); userRouter.put("/", (ctx) => { // json 方式传参 console.log(ctx.request.body); // 响应结果 ctx.body = "修改成功"; }); module.exports.userRouter = userRouter;
-
-
参数解析:form-data
-
请求地址:
http://localhost:8888/user/upload
-
body
是form-data
格式
-
-
解析body中的数据,我们需要使用multer
-
安装依赖:
npm install koa-multer
; -
使用
multer
中间件;// router/user.js const Router = require("koa-router"); const multer = require("koa-multer"); // 注意我这里安装的nanoid是3.x的版本,其它版本可能会报错 const { nanoid } = require("nanoid"); const { extname } = require("path"); const userRouter = new Router({ prefix: "/user", }); const storage = multer.diskStorage({ destination(req, file, cb) { cb(null, "uploads/"); }, filename(req, file, cb) { // 文件名 const fileName = nanoid(); // 文件的后缀名 const extName = extname(file.originalname); cb(null, fileName + extName); }, }); // 文件上传 const upload = multer({ storage, }); userRouter.post("/upload", upload.single("file"), (ctx) => { // form-data 方式传参 // 文件信息 console.log(ctx.req.file); // 表单数据 console.log(ctx.req.body); // 响应结果 ctx.body = "文件上传成功"; }); module.exports.userRouter = userRouter;
-
数据的响应
-
输出结果:
body
将响应主体设置为以下之一:-
string
:字符串数据ctx.response.body = "hello world";
-
Buffer
:Buffer
数据 -
Stream
:流数据 -
Object|| Array
:对象或者数组// Object ctx.body = { name: "why", age: 18, height: 1.88, };
// Array ctx.body = ["abc", "def", "nba"];
-
null
:不输出任何内容 -
如果
response.status
尚未设置,Koa
会自动将状态设置为200
或204
。
-
-
请求状态:
status
ctx.status = 201; ctx.response.status = 204;
静态服务器
-
koa并没有内置部署相关的功能,所以我们需要使用第三方库:
npm install koa-static
-
部署的过程类似于
express
:const Koa = require("koa"); const bodyParser = require("koa-bodyparser"); const static = require("koa-static"); const { userRouter } = require("./router/user"); const app = new Koa(); // bodyParser() 解析 json 数据的中间件 app.use(bodyParser()); app.use(static("./dist/index.html")); // 注册路由中间件 // userRouter.routes() 加载路由规则 // userRouter.allowedMethods() 对于没有实现和没有使用的请求方式做出正确的响应 app.use(userRouter.routes()).use(userRouter.allowedMethods()); app.listen(8888, () => { console.log("服务器开启成功"); });
和express对比
- 在学习了两个框架之后,我们应该已经可以发现
koa
和express
的区别: - 从架构设计上来说:
express
是完整和强大的,其中帮助我们内置了非常多好用的功能;koa
是简洁和自由的,它只包含最核心的功能,并不会对我们使用其他中间件进行任何的限制。- 甚至是在
app
中连最基本的get
、post
都没有给我们提供; - 我们需要通过自己或者路由来判断请求方式或者其他功能;
- 甚至是在
- 因为
express
和koa
框架他们的核心其实都是中间件:- 但是他们的中间件事实上,它们的中间件的执行机制是不同的,特别是针对某个中间件中包含异步操作时;