阅读 182

express VS koa

expresskoa 都是同一个团队弄出来的web 框架,分版本的目的是为了向 es6的标准靠齐。接下来我们就来聊聊这同一个团队因为什么样的事情,要重新做一个 koa 出来

express

express 出来的时候,js 还是处于混沌期间,es6的标准没有出来。而node的事件处理的方式都是基于 cb(callback) 的这种形式,在当时来看,这种方式是比较好的一种方式。所以express 里面的中间件处理的方式基本上都是回调。es6 的出现,带来了许多新的标准。使得express 不得不考虑需要兼容es6中的语法, 而 es6中处理异步的方式是promise,还有后面陆续的 async 和 await 等语法糖。(express 不是说不能使用这些语法糖,他使用第三方的库是可以解决的,只是没有koa那么优雅)

区别

这里的区别从koa的角度来看,对比 express

更轻量

koa 在express的基础上简化了框架,没有express 那么重,主要表现在下面两个方面:

  • koa 不提供内置的中间件;
  • koa 不提供路由,而是把路由这个库分离出来了(koa/router)

其实从两者的官网来分析可以看得到,koa 的官网就一个页面,而express向一个包含了各种各样中间件的框架。

结构不一样

express 的对象结构是下面这个样子的。

app.get('/', function (req, res) {
  	res.send('Hello World!')
})
复制代码

用一张图来表示如下:

image.png

对于koa来说的话,他比express多了一层context,这样的话对于在保存一些公有的参数的话变得更加合情合理。如下图:

image.png

koa 更加友好的支持中间件

为什么说更加友好呢,koa 在写法上支持异步的中间件写法。而对于express 来说的话,功能可以实现,但是在代码阅读上并不是那么的友好

假设我们有这么一个情况,需要 A-> B -> C -> B -> A 这样来执行中间件的顺序来执行同步代码 koa 和 express 没有区别。逻辑如下:

image.png

express 同步

app.use(function (req, res, next) {
  console.log(1);
  next();
  console.log(4);
  next();
})

// 中间件2
app.use(function (req, res, next) {
  console.log(3);
  next();
})
复制代码

结果

image.png

koa 同步

app.use(function (ctx, next) {
  console.log(1);
  next();
  console.log(4);
});

// 中间件2
app.use(function (ctx, next) {
  console.log(3);
  next();
})
复制代码

结果

image.png

这两者的代码对于同步处理来说,几乎没有区别。都能实现效果,但是往往写代码过程中,不太现实全是同步的需求。

异步处理

如果我们有这么个逻辑,如下图:

image.png

我们想要输出的顺序是 1 -> 2 -> 3 -> 4

express 中的处理

// 模拟异步
function delay(duration) {
  return new Promise(resolve => {
    setTimeout(() => {
      resolve();
    }, duration)
  })
}
// 中间件1
app.use(async function (req, res, next) {
  console.log(1);
  next();
  // 这一段逻辑我本来是需要放到第二个中间件中的,但是放到第二个中间件就实现不了功能了
  await delay(1000);
  console.log(3);
  
  
  console.log(4);
  next();
})

// 中间件2
app.use(asyncHandler(async function (req, res, next) {
  console.log(2);
}))
复制代码

image.png

这里虽然说实现了打印的结果,但是和我们的图中的逻辑是不一样的,是不对的。如果写成和图一样的逻辑。

// 模拟异步
function delay(duration) {
  return new Promise(resolve => {
    setTimeout(() => {
      resolve();
    }, duration)
  })
}
// 中间件1
app.use(async function (req, res, next) {
  console.log(1);
 await next();
  console.log(4);
  next();
})

// 中间件2
app.use(asyncHandler(async function (req, res, next) {
  console.log(2);
  await delay(1000);
  console.log(3);
}))
复制代码

代码是需要这样的逻辑的,但是结果却不一样了,如下:

image.png

原有就是express出现的时候,并没有promise和async await 等新的标准,express 可以实现功能,只是用了不一样的方式来做。

koa 实现

// koa 的中间件示例
function delay(duration) {
  return new Promise(resolve => {
    setTimeout(() => {
      resolve();
    }, duration)
  })
}
// 中间件1
app.use(async function (ctx, next) {
  console.log(1);
  await next();
  console.log(4);
})

// 中间件2
app.use(async function (ctx, next) {
  console.log(2);
  await delay(1000);
  console.log(3);
})
复制代码

image.png

可以看到,对于每个中间件,在完成了一些事情后,可以非常优雅的将控制权传递给下一个中间件,并能够等待它完成,当后续的中间件完成处理后,控制权又回到了自己,这种中间件模型称之为洋葱模型

image.png

文章分类
后端
文章标签