本文章原始创作地址:https://blog.csdn.net/qq_20264891/article/details/90216585
如您有其他建议,可以通过左上角的 QQ 发起回话,或者在 https://zq-jhon.github.io/about/ 中添加我的微信
为什么要学 Koa
,不学 Express
?
因为不想写回调,日常开发习惯 async await
处理异步流程,因此选择 Koa 2
。(以下简称 Koa)
Koa2 核心概念
洋葱模型 其实就是 async await
执行流程,在 koa
每次调用中间件时,回调函数中 next
会吧执行权递交给下一个回调函数。按笔者通俗的解释为:洋葱先从外侧切到内侧,再从内测切到另一边的外侧。其实也就是回调函数被 async await
化了而已。
ctx(context)
上下文,request
, response
都被合并封装到 ctx
中,方便每个中间件进行操作,调用。
打印一下 ctx
,可见,ctx
描述的是,每个完整的 http
所包含的信息,包括但不限于 请求方法(method
),url(request url
),响应码(status
), 响应信息 message
, header
等。
路由 路由的处理也是包含在中间件中的。路由的概念并不陌生,Angular
中除了基本的 Router 路由器让你处理跳转路由之外,还有 Activeted
路由,来处理不同的 Url
和接受 query
等。 在我看来,这里 Koa
的路由,其实跟 Angular Activeted
的概念很像。代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| app.use(async (ctx, next) => { if (ctx.request.path === "/") { ctx.response.body = "<h1>index Router</h1>"; } else { await next(); } });
app.use(async (ctx, next) => { if (ctx.request.path === "/todo") { ctx.response.body = "<h1>Todo Router</h1>"; } else { await next(); } });
|
完事。 Demo:
但官方已经有更好的中间件了:koa-router
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| const Koa = require("koa"); const app = new Koa(); const router = require("koa-router")();
router.get("/", async (ctx, next) => { ctx.response.body = "<h1>index Router</h1>"; });
router.get("/todo", async (ctx, next) => { ctx.response.body = "<h1>Todo Router</h1>"; });
app.use(router.routes());
|
具名路由:
1 2 3 4 5
|
router.get("user", "users/:id", async (ctx, next) => { ctx.response.body = `你要访问的是 : ${ctx.response.path}`; });
|
query param 以及 param 对象
1 2 3 4 5 6 7 8 9 10 11 12
|
router.get('/home/:id', async (ctx,next) => { ctx.response.type = 'application/json'; ctx.response.body = ctx.params; });
router.get('/home' async (ctx, next) => { ctx.response.type = 'application/json'; ctx.response.body = `${ctx.request.query}`; });
|
params:-object:
query-params:
拿 Angular
中的路由做一下类比:
1 2 3 4 5
| this.activitedRoute.paramMap.subscribe(param => console.log(param));
this.route.queryParamMap.subscribe(res => console.log(res));
|
都是根据浏览器的 urlParamsMap
来实现的。
body-parser
上述的所有请求, 都是基于 GET
请求的,那么如果客户端发来 post
请求,怎么解析 send 过来的数据呢?通过路由吗?做不到啊!所以还是得借助 ctx 上挂着的的对象来进行解析,因为 post 请求接受 form Data
也是异步的,所以要给 ctx.request
绑定监听:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
| const Koa = require("koa"); const router = require("koa-router")(); const app = new Koa();
app.use(async (ctx, next) => { ctx.body = ` <form action="/submit" method="post"> <input name="account" type="text"> 账号 <br/> <input name="password" type="password"> 密码 <br/> <button>提交</button> </form> `; await next(); });
app.use(async (ctx, next) => { if (ctx.request.url === "/submit") { const data = await parseData(ctx); ctx.response.body = data; } await next(); });
function parseData(ctx) { return new Promise((resolve, reject) => { try { let str = ""; ctx.req.on("data", data => { str += data; }); ctx.req.addListener("end", () => { resolve(str); }); } catch (err) { reject(err); } }); }
app.use(router.routes());
app.listen(3000, () => { console.log("server is running at http://localhost:3000"); });
|
Demo:
But, 不用这么麻烦,有对应的轮子了: koa-bodyparser
该中间件,会将 post 的数据,全部解析进 ctx.request.body
中
核心代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| const bodyparser = require("koa-bodyparser");
app.use(bodyparser());
app.use(async (ctx, next) => { ctx.body = ` <form action="/submit" method="post"> <input name="account" type="text"> 账号 <br/> <input name="password" type="password"> 密码 <br/> <button>提交</button> </form> `; await next(); });
app.use(async (ctx, next) => { if (ctx.request.url === "/submit") {
ctx.response.body = ctx.request.body; } await next(); });
|
来试试效果吧!
搞定了。
😘 觉得文章有用?点击下方打赏,鼓励作者更好的写作!