前端开发那些事儿

nodejs框架对比:koa和express

2021-05-16  本文已影响0人  miao8862

目前比较流行的nodejs框架有expresskoaegg.js,还有就是和ts相关的框架nest.js

无论是哪种框架,其核心都是基于中间件来实现的,而中间件执行的方式都跟洋葱模型有关,它们的差别主要也是在洋葱模型的执行方式上。

什么是洋葱模型?

洋葱模型,就像洋葱一样,一层包裹一层,而nodejs框架的执行就像是中间穿过洋葱的一条线,而每一层洋葱皮就代表一个中间件,进入时穿过多少层,出来时还得穿出多少层,具有先进后出(栈)的特点。

借鉴张图:洋葱模型

穿进来时:middleware1 -> middleware2 -> middleware3 -> center
穿出来时:center -> middleware3 -> middleware2 -> middleware1

Express

ExpressNode.js 初期就是一个热度较高、成熟的 Web 框架,并且包括的应用场景非常齐全。同时基于 Express,也诞生了一些场景型的框架,常见的就如上面我们提到的 Nest.js框架

KOA

随着nodejs发展,出现了以await/async为核心的语法糖,Express原班人马为了实现一个高可用、高性能、更健壮,并且符合当前Node.js 版本的框架,开发出了可定制KOA框架。
Egg.js 就是在 KOA 基础上,做了各种比较成熟的中间件和模块,可以说是在 KOA框架基础上的最佳实践,用以满足开发者开箱即用的特性。

所以在对比差异时,我们主要对比ExpressKOA就可以看出它们间的主要区别

Express和KOA的差异

下面来以例子说明一下两个框架的执行过程不一样的地方:

Express示例

  1. 写个express服务器
mkdir node-demo
cd node-demo
npm init -y
mkdir src
touch express.js
const express = require('express')
const app = express()
const port = 3000

const server = app.listen(port, () => {
  const host = server.address().address
  const port = server.address().port
  console.log(`Express server is listening on ${host}:${port}!`)
})

app.use((req, res, next) => {
  console.log('middleware1 start')
  next(); // 跳到下一层洋葱中间件
  console.log('middleware1 end')
})

app.use((req, res, next) => {
  console.log('middleware2 start')
  next(); // 跳到下一层洋葱中间件
  console.log('middleware2 end')
})

app.use((req, res, next) => {
  console.log('middleware3 start')
  next(); // 跳到下一层洋葱中间件
  console.log('middleware3 end')
})

app.get('/', (req, res) => {
  res.send('hello express')
})

  1. 启动服务
    node ./src/express-test.js
  2. 在浏览器访问http://localhost:3000/,结果如下:
    express服务器
  3. 关闭和管理服务
    关闭服务的操作:在当前目录下ctrl+c结束进程

KOA示例

KOA的用法其实和Express差不多,只不过Express内置了router,而KOA需要自己定制:

  1. 安装:npm i koa koa-router chalk
  2. 中间件的方法和Express基本一样,只不过将req, res参数换成了上下文ctx
  3. 设置路由需要用路由实例方法 router.get 方式,且要把路由实例设置到koa实例上app.use(router.routes())
const chalk = require('chalk')
const Koa = require('koa')
const Router = require('koa-router')
const app = new Koa()
const router = new Router()
const port = 9000

// 使用ctx上下文
app.use((ctx, next) => {
  console.log('middleware1 start')
  next(); // 跳到下一层洋葱中间件
  console.log('middleware1 end')
})

app.use((ctx, next) => {
  console.log('middleware2 start')
  next(); // 跳到下一层洋葱中间件
  console.log('middleware2 end')
})

app.use((ctx, next) => {
  console.log('middleware3 start')
  next(); // 跳到下一层洋葱中间件
  console.log('middleware3 end')
})
router.get('/', (ctx) => {
  ctx.body = 'Hello koa!'
})


// 使用router
app.use(router.routes())
app.listen(port, 'localhost', () => {
  console.log(chalk.yellow(`Express server is listening on ${port}!`))
})
koa服务器

可以看到如果是中间件中的代码是同步的时候,两者的的执行顺序是一样的。现在修改一下:

  1. 增加一个执行异步操作的中间件
  2. 每一个中间件,都增加上async await处理
// 这里只举一例子,其它的中间件是一样的
app.use(async (req, res, next) => {
  console.log('middleware1 start')
  await next(); // 跳到下一层洋葱中间件
  console.log('middleware1 end')
})
app.use(async (req, res, next) => {
  console.log('async start');
  await next();
  await new Promise(
      (resolve) => 
          setTimeout(
              () => {
                  console.log(`wait 1000 ms end`);
                  resolve()
              }, 
          1000
      )
  );
  console.log('async end');
});

此时,再观察两者的输出顺序:

Express是顺序不是严格按照洋葱模型的:

Express

KOA的顺序是严格按照洋葱模型的:

koa

发生这样的原因是两者基于的nodejs的版本不一样导致的。

参考:
https://blog.csdn.net/xgangzai/article/details/109108387
https://www.jianshu.com/p/6f7930687835/

上一篇 下一篇

猜你喜欢

热点阅读