package pack区别(koa 和 express 的对比)
前言
天冷了 ,唯有学习来温暖自己 。
最近利用业余的时间 ,跟着 coderwhy 老师学习 node.js ,了解以及掌握一些服务端的常见知识:
fileSystem:文件读取模块 。 events:事件流 Buffer:node 中处理二进制的方式 http 创建服务器 Stream流的读写操作 …确实学习到了很多东西 ,填充了自己的知识体系的未知领域 。
node.js 也许是前端开发者踏入服务端开发的最好选择 。同样的 JavaScript ,同样的语法 ,以及同样的你 ,基本上可以达到无缝衔接的开发 。
对于 node.js 而言 ,社区里面出现了非常多的框架 ,快速上手,敏捷开发 。
koa 和 express 就是其中的比较两个突出的框架 。
在阅读下文之前 ,希望你掌握了 express 和 koa 的基本使用 ,不然下面内容对你的帮助也许不是那么的大 。
koa 和 express 的介绍
express 是一个基于 node.js 平台,快速 ,开放 ,极简的 web 开发框架 。express 官网
koa 是基于 node.js 平台的下一代 web 开发框架。koa 官网
两个框架都是同一个团队开发的,都是 node.js 中比较优秀的框架 。
都是 node.js 框架 ,同一个团队为什么要开发两个呢?
express 也许是 node.js 最早出的框架 ,里面集成了大量的中间件 ,造成了框架的笨重性 。团队领队人 TJ 发现了 express 的设计是有缺陷的 ,如果想要修复这个设计缺陷 ,就会造成 express 的框架重构。
基于上面的种种原因(当然还有不知道的) ,就打算重新写一个新的框架->koa ,来实现 express 的不足之处 。
express 现在有团队中的团员维护 ,基本上也很少更新了 。
koa 由团队领队人 TJ 主要维护。
--来自 coderwhy 老师的闲谈
上面的闲谈的内容不重要 ,当个乐子开心一下就好了 。
一起看看 express 和 koa 在 github 上的星标:
可以发现 express 的使用率还是比 koa 高,尽管 express 笨重 ,设计有缺陷 ,但是对于开发者而言,当不考虑这些因素情况下 ,express 还是吃香的 。两者都是同一团队写的两个框架 ,那么核心的思想肯定是相同的,当然肯定会也存在差异 ,那么接下来就来重点比较一下其中的差异吧 。
koa 和 express 的差异对比
下面主要从两个方面来分析其中的差异:设计架构 、中间件 。
因为也是第一次接触 koa (express 以前是接触了的) ,如果存在有误的地方 ,请指出来 ,虚心受教 ,共同进步 。
koa 和 express 的设计架构对比
express 是完整和强大
的 ,里面集成了大量的中间件 ,比如说:路由 ,静态资源等中间件 。对于开发者而言 ,技术统一,都是使用 express 内部提供的 。
koa 是灵活和自由的 ,基本上没有集成任何中间件(核心代码只有大致1600行左右) ,中间件都需要自己去安装 。对于开发者而言,选择技术的类型是多样的 ,丰富的 。
webstorm 和 vscode 的使用 ,都是因人而异,没有谁强谁弱。那么对于 express 和 koa 也是同样的道理 ,各自有各自优势 。
接下来我们一起来听听 express 和 koa 独白:
express:hi ,koa ,我俩同处一体 ,我俩比比?
koa:???
express:我俩的发动机都是中间件 ,我有三个兄弟:request ,response ,next ,你有几个兄弟呢?
koa:额 ,我有两个兄弟:context,next 。不过我这 context 兄弟很厉害 ,以一敌二(request ,response)。
express:我自带路由(Router),直接使用即可 ,你呢?
koa:安装 。(koa-router 或者 @dva/router)
express:我可以自己暴露静态资源 ,你呢?
koa:安装 。(koa-static)
express:我只需要配置一下,就可以解析客户端传递 application/json 的格式数据 ,你呢?
koa:还是安装。(koa-bodyparser)
express:你能不能不要安装呀 ,你就没有自带的?我还是只需要配置一下 ,就可以解析客户端传递 x-www-form-urlencoded 的格式数据 ,你呢?
koa:哈哈哈 ,不好意思 ,我不用配置 ,我也能解析 x-www-form-urlencoded 的格式数据 。
koa:我还能安装 @koa/multer 来实现文件上传 ,你自带了吗?
express:额 。 。 。我这个还真没自带 ,我也需要安装 multer 来实现 。
koa:让你装 xxx 。你我本是同根生,相煎何太急 ,和平相处不行嘛 。
express: 。 。。
TJ:莫吵了 ,把你俩创建出来,设计理念本就是不相同的 。express 你走的完整路线 ,koa 走的是灵活路线 ,所以不用相互较劲,和气生财 。
koa 和 express 的中间件对比
express 和 koa 的核心 ,都是中间件。
简单的来说 ,理解了中间件 ,也就理解了express 和 koa 。
何为中间件?那么何为中间件呢?
express 和 koa 都能创建一个服务器实例 app ,那么给 app 传入一个回调函数 ,那么该回调函数就被称为中间件(middleware) 。
express 创建中间件:
// 方式一:use(fn) app.use((req, res, next) => {}) // 方式二:use(path, fn) app.use(/, (req, res, next) => {}) // 方式三:method(path, fn) app.get(/, (req, res, next) => {}) // 方式四:method(path, fn1, fn2, fn3) app.get(/, (req, res, next) => {}, (req, res, next) => {})koa 创建中间件:
// 方式一:use(fn) app.use((ctx, next) => {}) // 方式二:use(path, fn) app.use(/, (ctx, next) => {})在这里就不展开怎么使用中间件了 ,我相信你会的 ,express 和 koa 的中间件道理是相同的。
中间件的执行顺序(同步 ,异步) express 同步 app.use((req, res, next) => { console.log("中间件01: next前"); next(); console.log("中间件01: next后"); }); app.use((req, res, next) => { console.log("中间件02: next前"); next(); console.log("中间件02: next后"); }); app.use((req, res, next) => { console.log("中间件03") }); express 异步 function mockAsync () { return new Promise((resolve) => { setTimeout(() => { resolve(321) }, 1000) }) } app.use((req, res, next) => { console.log("中间件01: next前"); next(); console.log("中间件01: next后"); }); app.use((req, res, next) => { console.log("中间件02: next前"); next(); console.log("中间件02: next后"); }); app.use(async (req, res, next) => { const data = await mockAsync() console.log("中间件03: next前"); }); koa 同步 app.use((ctx, next) => { console.log(中间件01: next前); next() console.log(中间件01: next后); }) app.use((ctx, next) => { console.log("中间件02: next前"); next(); console.log("中间件02: next后"); }); app.use((ctx, next) => { console.log("中间件03"); }); koa 异步 function mockAsync() { return new Promise((resolve) => { setTimeout(() => { resolve(321); }, 1000); }); } app.use((ctx, next) => { console.log(中间件01: next前); next() console.log(中间件01: next后); }) app.use((ctx, next) => { console.log("中间件02: next前"); next(); console.log("中间件02: next后"); }); app.use(async (ctx, next) => { const res = await mockAsync() console.log("中间件03"); });上面四个案例 ,分别从:
express 同步 express 异步 koa 同步 koa 异步来分析了中间的执行顺序,可以得出两点结论:
无论是 express 还是 koa ,当中间件是同步代码并且调用了 next 函数 ,那么程序运行就会先执行每个中间件next函数之前的代码,当执行到最后一个中间件时 ,又会回滚执行每个中间件next 函数后的代码(类似于 数据结构中的 first in last out) 。 无论是 express 还是 koa ,当遇到中间件中存在异步代码,就会停止向下执行 ,而是回到上一个中间件继续执行 。所以对于 express 和 koa 在中间件执行上 ,**表现形式**上是相同的 。
而不相同之处就是在于 express 和 koa 在针对中间件存在异步代码时 ,**处理方式**不同(简单的来说也就是内部的 next 函数实现不同) 。
koa 和 express 不同的异步处理方式假如存在这样的一个案例:存在两个中间件 ,一个是业务接口处理的中间件 ,一个是针对处理相同数据的中间件(比如:针对每个接口返回用户信息) ,这里的获取用户信息 ,就是异步操作 。
那么针对 express 会写出以下代码:
function getUserInfo () { return new Promise((resolve) => { setTimeout(() => { resolve({name: copyer, sex: man}) }, 1000) }) } app.get(/list, (req, res, next) => { const list = [ { id: "1", content: "列表1" }, { id: "2", content: "列表2" }, ]; next(); res.json({ list, userInfo: req?.userInfo // 返回用户信息 ,需要通过下个中间件来获取 }) }); app.use(async (req, res, next) => { // mock 异步代码 ,拿到用户信息 const data = await getUserInfo(); console.log(data); // { name: copyer, sex: man } req.userInfo = data; // 设置用户信息 });当我们访问 list 接口时,发现是拿不到用户信息(userInfo),因为遇到是异步函数 ,就会停止继续执行下面的代码 ,而是回到上一个中间件继续执行,所以没有拿到用户信息 。
koa 也是同样的道理 ,但是 koa 却是可以解决这个问题 。代码如下:
function getUserInfo() { return new Promise((resolve) => { setTimeout(() => { resolve({ name: "copyer", sex: "man" }); }, 1000); }); } router.get(/list, async (ctx, next) => { const list = [ { id: "1", content: "列表1" }, { id: "2", content: "列表2" }, ]; await next(); /*****************重点代码*********************/ ctx.body = { list, ctx: ctx?.userInfo } }); router.use(async (ctx, next) => { const res = await getUserInfo(); console.log(res); // { name: copyer, sex: man } ctx.userInfo = res; // 设置用户信息 }); app.use(router.routes())看上面标记的重点代码 ,那么就是处理异步的关键 。在 next 执行前面,加上一个 await ,这样就能正常的拿到用户信息 。
await next() 的意思就是等待下个中间件执行完成 ,那么这样用户信息也就设置成功了。
那么肯定有人这样想 ,那么我在 express 调用 next 函数时 ,也加上 await ,是不是也解决了?想法很美好 ,但是行不通的 。为撒?
express 中的 next 函数 ,返回值一个void ,没有返回值 。
这里的 next 函数接受一个参数 err ,也就是错误信息,针对全局异常处理的收集时 ,就会使用。
koa 中的 next 函数 ,返回值一个Promise 。
这里的 next 函数不接受参数,所以全局错误的异常处理 ,需要另想它法 。
koa 和 express 在异步处理函数 ,最大的差别就是 next 函数实现不同,那么也就造成了中间件在异步上的使用不同。
koa 在上一个中间件拿取下一个异步中间件的数据 ,然后返回 。express 却是不行 ,这是 express 设计上的缺陷 。
洋葱模型
想想平时生活中的洋葱 ,是不是一层一层的 。
中间件从上往下(从外往里) ,然后从下往上(从里往外)执行 ,无论是同步还是异步都满足 ,koa 是符合洋葱模型的 。
express 是在同步的时候是满足洋葱模型的 ,但是异步的时候却是不能满足洋葱模型 。
总结
这篇主要从设计架构和中间件两个方面来解释说明 express 和 koa 之间的差异 。
比较差异并不是为了证明谁好谁弱 ,而是为了另一方面来充分认识框架隐藏的知识点 ,加深自己理解 。
若你觉得有误,请指出;若对你有用 ,请点个赞 。
创心域SEO版权声明:以上内容作者已申请原创保护,未经允许不得转载,侵权必究!授权事宜、对本内容有异议或投诉,敬请联系网站管理员,我们将尽快回复您,谢谢合作!