✅ 作者简介:一名普通本科大三的学生,致力于提高前端开发能力
✨ 个人主页:前端小白在前进的主页
🔥 系列专栏 : node.js学习专栏
⭐️ 个人社区 : 个人交流社区
🍀 学习格言: ☀️ 打不倒你的会使你更强!☀️
💯 刷题网站:这段时间有许多的小伙伴在问有没有什么好的刷题网站,博主在这里给大家推荐一款刷题网站:👉点击访问牛客网👈牛客网支持多种编程语言的学习,各大互联网大厂面试真题,从基础到拔高,快来体验一下吧!
🔥前言
在现阶段项目开发过程中,虽然express框架仍然占据着主导的地位,但是有部分的公司也使用了Koa框架开发,那么我们仍然需要学习一下Koa框架,本篇文章将从
Koa框架的入门
以及
与Express框架的不同之处
做为切入点去讲解!
📃目录
Koa框架简介
koa 是由
Express 原班人马
打造的,致力于成为一个
更小、更富有表现力、更健壮
的 Web 框架。使用 koa 编写 web 应用,通过组合不同的 generator,可以免除重复繁琐的回调函数嵌套,并极大地提升错误处理的效率。koa
不在内核方法中绑定任何中间件,它仅仅提供了一个轻量优雅的函数库
,使得编写 Web 应用变得得心应手。
Koa框架的优点
- Koa提高了互操作性,健壮性,使编写中间件变得更加愉快。
- 集成了大量的web API,但是没有绑定中间件
- 非常轻量,核心的Koa模块只有大约2K行代码
- 拥有非常好的用户体验
- 通过try / catch更好地处理错误
- 异步控制流,代码可读性更高
Koa框架的缺点
- Koa框架的周边生态并无优势
- 与Express风格的中间件并不兼容
- 对开发者要求可能更高一些
快速开始
安装Koa
npm install koa
注意: Koa需要node
v7.6.0以上版本支持
,因为内部使用了
ES6
的特性。
Hello Koa
const Koa =require('koa')const app =newKoa()
app.use(async(ctx)=>{
ctx.body ='hello koa2'//ctx.body = '<b>hello koa2</b>' //返回html片段//ctx.body = {name:'james'} //返回的是json格式数据})
app.listen(3000)
注意: 我们默认使用的是
Koa2
,koa2与koa1的
最大区别
是koa2实现异步是通过
async/await
,koa1实现异步是通过
generator/yield
,Koa2更加的便利,所以默认选用Koa2。
ctx对象
我们在这里可以明显的发现,Koa与Express不同之处在于中间件的形参传的不一样了,我们在Expess中两个参数
req
,
res
在这里被
ctx
所替代了。
ctx全称是
context
(汉译:
上下文
),这个在所有语言里都有的名词,可以理解为
上(request)下(response)沟通
的环境,所以koa中把他们两都封装进了ctx对象,koa官方文档里的解释是为了调用方便
ctx.req=ctx.request,ctx.res=ctx.response,ctx.body = ctx.res.body = ctx.response.body
Koa 提供一个 Context 对象,表示一次对话的上下文(包括 HTTP 请求和 HTTP 回复)。通过加工这个对象,就可以控制返回给客户端的内容。例如上方代码中的
ctx.body = 'hello koa2'
,在前端页面中会显示
hello Koa2
我们可以在终端打印一下
ctx
对象:
{request:{method:'GET',url:'/favicon.ico',header:{host:'localhost:3000',connection:'keep-alive','sec-ch-ua':'" Not A;Brand";v="99", "Chromium";v="101", "Google Chrome";v="101"','sec-ch-ua-mobile':'?0','user-agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.0.0 Safari/537.36','sec-ch-ua-platform':'"Windows"',accept:'image/avif,image/webp,image/apng,image/svg+xml,image/*,*/*;q=0.8','sec-fetch-site':'same-origin','sec-fetch-mode':'no-cors','sec-fetch-dest':'image',referer:'http://localhost:3000/','accept-encoding':'gzip, deflate, br','accept-language':'zh-CN,zh;q=0.9,en;q=0.8',cookie:'Webstorm-a5eae5c4=895fa835-890a-4be8-97fa-9d70b377e3fc; _ga=GA1.1.1673643516.1666519138'}},response:{status:200,message:'OK',header:[Object:null prototype]{'content-type':'text/html; charset=utf-8','content-length':'17'}},app:{subdomainOffset:2,proxy:false,env:'development'},originalUrl:'/favicon.ico',req:'<original node req>',res:'<original node res>',socket:'<original node socket>'}
其实我们很容的发现,它里面的
request
和
reponse
其实分别是
HTTP Request
和
HTTP Response
,随之进行相应的操作就好了!
补充
- ctx.request与ctx.req的区别: ctx.request是
context经过封装的请求对象,用起来更直观和简单
;ctx.req是context提供的node.js原生HTTP请求对象,可以得到更多的内容
。同理ctx.response是context经过封装的响应对象,ctx.res是context提供的node.js原生HTTP响应对象。 - 绕过Koa的response处理是不被支持的,我们应该去避免使用以下node属性:
ctx.res.statusCode、ctx.res.writeHead()、ctx.res.write()、ctx.res.end()
Koa对比Express
通常都会说 Koa 是
洋葱模型
,这
重点在于中间件的设计
。通过分析,会发现 Express 也是类似的,不同的是
Express 中间件机制使用了 Callback 实现
,这样
如果出现异步则可能会使你在执行顺序上感到困惑
,因此
如果我们想做接口耗时统计、错误处理
Koa 的这种中间件模式处理起来更方便些。最后一点响应机制也很重要,
Koa 不是立即响应,是整个中间件处理完成在最外层进行了响应,而 Express 则是立即响应
。
更轻量
- koa
不提供内置的中间件
; - koa
不提供路由
,而是把路由这个库分离出来了(koa/router)
Context对象
koa增加了一个Context的对象,作为这次请求的上下文对象(在koa2中作为中间件的第一个参数传入)。同时Context上也挂载了Request和Response两个对象。和Express类似,这两个对象都提供了大量的便捷方法辅助开发, 这样的话对于在保存一些公有的参数的话变得更加合情合理。
异步流程控制
express采用
callback
来处理异步, koa v1采用
generator
,koa v2 采用
async/await
。
generator和async/await使用同步的写法来处理异步,明显好于callback和promise,
中间件模型(洋葱模型)
express基于connect中间件,
线性模型
;
koa中间件采用
洋葱模型
(对于每个中间件,在完成了一些事情后,可以非常优雅的将控制权传递给下一个中间件,并能够等待它完成,当后续的中间件完成处理后,控制权又回到了自己)
代码示例:
Express与Koa的
同步代码
比较:
Express:
//同步var express =require("express")var app =express()
app.use((req,res,next)=>{
console.log(1)next()
console.log(4)
res.send("hello")})
app.use(()=>{
console.log(3)})
app.listen(3000)
最终的打印结果顺序是
134
,浅而意见的看出Express框架中间件是
线性模型
,明显有顺序性。
注意: 在一般情况下我们在express框架中的
next()
下方不会再书写代码,这里只是做对比使用。
Koa:
//同步const koa =require("koa")const app =newkoa()
app.use((ctx,next)=>{
console.log(1)next()
console.log(4)
ctx.body="hello"})
app.use(()=>{
console.log(3)})
app.listen(3000)
最终的打印结果顺序是
134
,从这里其实并不能看出来Koa的洋葱模型,但是下面的异步代码中可以非常清晰的看出洋葱模型。
Express与Koa的
异步代码
比较:
Express(在这里使用了洋葱模型去书写express,可以发现有不合理的地方):
const express =require("express")const app =express()
app.use(async(req,res,next)=>{
console.log(1)awaitnext()
console.log(4)
res.send("hello")})
app.use(async()=>{
console.log(2)awaitdelay(1000)
console.log(3)})functiondelay(time){returnnewPromise((resolve,reject)=>{setTimeout(resolve,1000)})}
最终的打印结果顺序是
1243
,在这里大家可能有迷惑的地方,我们第一个中间件中已经具有代码
await next()
了,那么为什么打印结果不是
1234
呢?那是因为
next()
并不是一个
promise对象
,await只会对promise对象起作用!
Express线性模型的写法:
const express =require("express")const app =express()
app.use(async(req,res,next)=>{
console.log(1)awaitnext()})
app.use(async()=>{
console.log(2)awaitdelay(1000)
console.log(3)
console.log(4)
res.send("hello")})functiondelay(time){returnnewPromise((resolve,reject)=>{setTimeout(resolve,1000)})}
最终的打印结果顺序是
1234
,在这里就可以明显看出来,第一个中间件执行完后,先打印了
1
,随后进入第二个中间件,先打印出来
2
,然后等待一秒钟后,打印了
34
.
Koa洋葱模型写法:
const koa =require("koa")const app =newkoa()
app.use(async(ctx,next)=>{
console.log(1)awaitnext()
console.log(4)
ctx.body="hello"})
app.use(async()=>{
console.log(2)awaitdelay(1)
console.log(3)})functiondelay(time){returnnewPromise((resolve,reject)=>{setTimeout(resolve,1000)})}
app.listen(3000)
最终的打印结果顺序是
1234
,我们通过分析可以看出来它遵循的就是洋葱模型,第一个中间件打印了
1
,然后进入第二个中间件,打印
2
之后,等待一秒,打印出来了
3
,随后又返回了第一个中间件,打印出
4
。
通过异步代码的对比,我觉得大家可能看的迷迷糊糊了,可能不明白为什么我们通过打印顺序去观察相应的模型,在实际开发中有什么业务可以满足这种需求呢?
假如我们已经进入了一个页面,但是从这个页面再获取一些数据的时候需要携带token才能获取,我们就可以采用洋葱模型
。
例如:打印
1
是代表已经进入了某个页面并且获取了一些公共数据,但是我们现在需要登录用户后才能获取另外一批数据,于是我们进入了第二个中间件,打印
2
是执行登录过程的业务,登录的进行过程(
delay延时1秒钟
)度过后,后端返回了token,返回token就是打印
3
,然后我们又回到第一个中间件,携带token去访问接口获取数据(打印
4
).
小结
Koa框架明显的好处就是轻量级别,并且有着非常良好的异步体验,本文对Koa框架做一个简单的了解,并且区分了与Express框架的不同之处,至于怎么去选择使用哪个框架,在后面的学习中相信会给大家一个答案的,继续加油吧!少年😀😀
版权归原作者 前端小白在前进 所有, 如有侵权,请联系我们删除。