当前位置: 首页 > news >正文

再谈express与koa的对比

以前其实写过一篇express和koa的对比, 但是后来发现里面有不少谬误. 所以一直惦记着纠正一下之前的错误, 尤其关于中间件部分的对比.

这里的express就拿更加简单的connect代替

connect的执行流程

通常我们都说connect的中间件模型是线性的, 也就是一个一个往下执行的, 如下图:

image

这么说当然是没错的, 但是当我们执行下面代码的时候可能会有那么一点小小的困惑:

const connect = require('connect')

const app = connect()

app.use(function m1 (req, res, next) {
  console.log('m1')
  next()
  console.log('m1 end')
})

app.use(function m2 (req, res, next) {
  console.log('m2')
  next()
  console.log('m2 end')
})

app.use(function m3 (req, res, next) {
  console.log('m3')
  res.end('hello')
})

app.listen(8080)

当我们访问http://127.0.0.1:8080的时候, 控制台会打印如下:

m1
m2
m3
m2 end
m1 end

这么个结果跟我们上面的模型似乎有点出入, 不是说线性的吗, 为什么next后面的代码还会继续执行? 当然这个我们再之前已经有过结论了, 有兴趣的可以详细瞧瞧, 我们现在直接拿来结果, connect的中间件模型伪代码表示如下:

http.createServer(function (req, res) {
  m1 (req, res) {
    m2 (req, res) {
      m3 (req, res) {}
    }
  }
})

可以看到就是一层一层嵌套的回调, 那么再把我们之前有点疑问的代码简化一下:

http.createServer(function (req, res) {
  console.log('m1')
  m1 (req, res) {
    console.log('m2')
    m2 (req, res) {
      m3 (req, res) {
        console.log('m3')
        res.end('hello')
      }
    }
    console.log('m2 end')
  }
  console.log('m1 end')
})

千万别被上面的回调绕晕了, 就是很简单的回调函数, 一切都解释的通了: 即使res.end之后, 我们的代码还是要继续往下走的, 可以这么说connect的中间件其实也是洋葱形的, 但是因为作为同步代码, 一般不回这么做罢了, 那么上面我们可以重现描述一下connect的中间件模型了:

image

Koa的执行流程

同样我们再Koa源码分析, 也是说过Koa的中间件模型: 洋葱形
image

以下面代码为例:

const Koa = require('koa')

const app = new Koa()

app.use(async function m1 (ctx, next) {
  console.log('m1')
  await next()
  console.log('m1 end')
})

app.use(async function m2 (ctx, next) {
  console.log('m2')
  await next()
  console.log('m2 end')
})

app.use(async function m3 (ctx) {
  console.log('m3')
  ctx.body = 'hello'
})

app.listen(8080)

访问服务, 输出:

m1
m2
m3
m2 end
m1 end

emm 貌似跟connect没差别, 之前看过一篇文章, 实验到这里得到了一个koa和express的中间件模型没差别的结论, 包括我也是很迷惑, 当然是有差别的, 结论后面讲. 同样这里直接拿出koa中间件的简化模型:

Promise.resolve(async m1 () {
  console.log(m1)
  await Promise.resolve(async m2 () {
    console.log(m2)
    await Promise.resolve(async m3 () {
      console.log(m3)
      ctx.body = 'xxx'
     })
     console.log(m2 end)
  })
  console.log(m1 end)
})

我们知道async/await的作用是'同步化'异步操作(看上去如此, 其实不是, 但是我们不需要去管), 那这里的Promise理所当然的被'同步'了, 也就是说console.log(m3 end)的一切异步操作都可以'同步化'.

结论

说出结论之前我们其实可以想一下, 既然connect的中间件也是洋葱形的, 那么跟koa一样的用法似乎也没啥毛病, 那么我来设想一下, 我们的服务需要取数据库里的的一个用户假设是getUser吧, getUser当然是异步的. 分别来看看connect和koa的做法吧:

// connect

app.use(function (req, res) {
  getUser(user => res.end(user))
})


// Koa
app.use(async (ctx) => {
  const user = await getUser()
  ctx.body = user
})

当然这么看似乎没啥差别. 那直接给出结论吧(憋): connect的中间件是同步, 不会'等'其他异步操作, koa则可以'等'异步操作. 当然你不等也没啥问题.

有啥问题可以互相交流哈.

image

相关文章:

  • [Android学习笔记]ScrollView的使用
  • 替换
  • 最长公共子串 NYOJ 36
  • 第一个Shader的更新,增加爆光度, 属性改为数值型(更直观,精确)
  • linuxdeepin 启动器启动之后出现白屏 的解决办法
  • js 事件详解 冒泡
  • simple-spring-memcached简介
  • [SPOJ]COT2
  • 设置时间
  • 28次课(使用w查看系统负载、vmstat命令、top命令、sar命令、nload命令)
  • 错误:update 忘了加 where
  • 编程常用动词细微差别
  • lpeg学习笔记- -
  • nslookup工具的使用方法
  • 菜鸟入门【ASP.NET Core】2:部署到IIS
  • 【挥舞JS】JS实现继承,封装一个extends方法
  • canvas 高仿 Apple Watch 表盘
  • ES6系统学习----从Apollo Client看解构赋值
  • JavaScript函数式编程(一)
  • Material Design
  • ng6--错误信息小结(持续更新)
  • OSS Web直传 (文件图片)
  • PHP 程序员也能做的 Java 开发 30分钟使用 netty 轻松打造一个高性能 websocket 服务...
  • PHP那些事儿
  • 从零到一:用Phaser.js写意地开发小游戏(Chapter 3 - 加载游戏资源)
  • 大数据与云计算学习:数据分析(二)
  • 马上搞懂 GeoJSON
  • 深入体验bash on windows,在windows上搭建原生的linux开发环境,酷!
  • 【干货分享】dos命令大全
  • ​DB-Engines 11月数据库排名:PostgreSQL坐稳同期涨幅榜冠军宝座
  • # C++之functional库用法整理
  • (1)Map集合 (2)异常机制 (3)File类 (4)I/O流
  • (11)MATLAB PCA+SVM 人脸识别
  • (9)目标检测_SSD的原理
  • (ctrl.obj) : error LNK2038: 检测到“RuntimeLibrary”的不匹配项: 值“MDd_DynamicDebug”不匹配值“
  • (delphi11最新学习资料) Object Pascal 学习笔记---第5章第5节(delphi中的指针)
  • (附源码)ssm考生评分系统 毕业设计 071114
  • (全注解开发)学习Spring-MVC的第三天
  • (算法)N皇后问题
  • (转)Mysql的优化设置
  • . ./ bash dash source 这五种执行shell脚本方式 区别
  • .cn根服务器被攻击之后
  • .desktop 桌面快捷_Linux桌面环境那么多,这几款优秀的任你选
  • .Net 4.0并行库实用性演练
  • .net mvc actionresult 返回字符串_.NET架构师知识普及
  • .NET 中什么样的类是可使用 await 异步等待的?
  • .NET 中小心嵌套等待的 Task,它可能会耗尽你线程池的现有资源,出现类似死锁的情况
  • .NET大文件上传知识整理
  • .vue文件怎么使用_我在项目中是这样配置Vue的
  • @Transactional 竟也能解决分布式事务?
  • [ 常用工具篇 ] AntSword 蚁剑安装及使用详解
  • [20171102]视图v$session中process字段含义
  • [BZOJ 3531][Sdoi2014]旅行(树链剖分+线段树)
  • [BZOJ5250][九省联考2018]秘密袭击(DP)
  • [CTF]php is_numeric绕过