1. Express 中间件

特点

  • 基于回调链(next 传递控制权)
  • 中间件本质就是 (req, res, next) 的函数。
  • 执行顺序是 线性串行,一旦调用 next() 就会交给下一个中间件,并且立即执行,无法感知异步或者完成态。
  • 正因为这种架构,必须使用 next(err) 捕获异常,而且异步情况也会出错(一般使用相关异步错误纠正的中间件解决)

示例

const express = require('express')
const app = express()

// 耗时统计中间件
app.use((req, res, next) => {
  const start = Date.now()

  next()

  const cost = Date.now() - start
  console.log('cost:', cost, 'ms')
})

// 模拟异步业务
app.get('/test', async (req, res) => {
  await new Promise(r => setTimeout(r, 100))
  res.send('ok')
})

app.listen(3000)
// cost: 1 ms 明显错误
// next() 只是“跳到下一个中间件”
// Express 不会等路由里的 async 完成,无法感知异步
// 统计到的只是“调度耗时”

👉 特点是 没有“洋葱模型”,执行顺序就是一条直线:


2. Koa 中间件

特点

  • 基于 async/await 实现。
  • 使用的是 洋葱模型:先进入外层中间件 → 一直到底 → 然后再从底层往外层“返回”。
  • 中间件函数签名:async (ctx, next)

示例

const Koa = require('koa')
const app = new Koa()

app.use(async (ctx, next) => {
  const start = Date.now()

  await next()

  const cost = Date.now() - start
  console.log('cost:', cost, 'ms')
})

// 模拟异步业务
app.use(async ctx => {
  await new Promise(r => setTimeout(r, 100))
  ctx.body = 'ok'
})

app.listen(3000)
// cost: 110 ms 天然正确

更多推荐