洋葱模型
什么是洋葱模型?
洋葱模型是一种中间件架构模式,得名于其执行过程像剥洋葱一样层层深入再层层返回的特点。它广泛应用于 Node.js 的 Web 框架中,如 Koa.js。
特点:
双向执行流程:
- 请求阶段:从外层中间件向内层执行
- 响应阶段:从内层中间件向外层返回
控制权传递:
- 每个中间件通过
next()函数将控制权传递给下一个中间件 - 只有当后续中间件执行完毕后,才会回到当前中间件继续执行剩余代码
- 每个中间件通过
错误处理:
- 可以在任意中间件捕获后续中间件抛出的错误
- 提供统一的错误处理机制
基础版
ts
export type Next = () => Promise<void>
export type Middleware<T> = (context: T, next: Next) => Promise<void>
export class OnionModel<T = any> {
private middlewares: Middleware<T>[] = []
// 添加中间件
use(middleware: Middleware<T>): this {
this.middlewares.push(middleware)
return this
}
// 执行中间件链
async execute(context: T): Promise<void> {
const dispatch = (i: number): Promise<void> => {
if (i >= this.middlewares.length) return Promise.resolve()
const middleware = this.middlewares[i]
return Promise.resolve(middleware(context, () => dispatch(i + 1)))
}
return dispatch(0)
}
}使用示例
ts
import { OnionModel } from './base'
// 使用示例
interface Context {
count: number
}
// 创建洋葱模型实例
const app = new OnionModel<Context>()
// 添加中间件 - 按顺序执行
app.use(async (ctx, next) => {
ctx.count++
console.log('Middleware 1 start', ctx)
await next()
console.log('Middleware 1 end', ctx)
})
app.use(async (ctx, next) => {
ctx.count++
console.log('Middleware 2 start', ctx)
await next()
console.log('Middleware 2 end', ctx)
})
app.use(async (ctx, next) => {
ctx.count++
console.log('Middleware 3 start', ctx)
await next()
console.log('Middleware 3 end', ctx)
})
// 执行并查看结果
async function run() {
const context: Context = { count: 0 }
await app.execute(context)
console.log('Final result:', context)
}
run()
/* 输出
Middleware 1 start { count: 1 }
Middleware 2 start { count: 2 }
Middleware 3 start { count: 3 }
Middleware 3 end { count: 3 }
Middleware 2 end { count: 3 }
Middleware 1 end { count: 3 }
Final result: { count: 3 }
*/