闭包通过词法环境绑定和状态共享实现时序约束,每个节点为返回闭包的工厂函数,固化阶段名、前置条件与依赖;requireOrder装饰器统一校验执行顺序,history与日志提供可断言的调用序列。

闭包本身不直接提供调用顺序校验能力,但它能天然承载和封装执行上下文与状态,是构建**可验证时序行为的流水线执行器**的理想基础。关键不在于“用闭包模拟 Spock 的 then: 块”,而在于利用闭包的词法环境绑定特性,把“预期顺序”显式编码为执行流程中的阶段约束。
用闭包封装阶段与期望
每个流水线节点不是一个孤立函数,而是一个返回闭包的工厂函数,该闭包内部固化了:当前阶段名、前一阶段标识、输入校验逻辑、以及对下一阶段的隐式依赖声明。
- 例如:validateThenTransform 不是直接做校验+转换,而是返回一个闭包,它只接受合法校验后的数据,并在成功后自动触发 transform 阶段的注册回调
- 闭包捕获外层传入的 stageId 和 expectedPrev,运行时即可比对实际调用链是否满足 stageId == 'transform' 且上一完成阶段是 'validate'
- 这样,顺序不再是靠测试断言去“事后检查”,而是由闭包在构造时就定义好“谁可以调我、我调谁”的契约
状态驱动的执行流控制
整个流水线实例持有一个可变但受控的状态对象(如 { currentStage: null, history: [] }),所有节点闭包都通过引用共享它。每次调用节点闭包时,先校验 state.currentStage 是否匹配本阶段前置条件,再更新 state 并记录 history。
- 若某节点被跳过或乱序调用(比如 transform 在 validate 前被手动触发),闭包内校验立即失败并抛出明确错误
- history 数组天然形成调用序列快照,可在任意时刻断言 history == ['init', 'validate', 'transform', 'output']
- 相比纯函数式 pipeline(如 Go 的 func(ctx, in)→out),这种带状态闭包结构让“顺序”成为运行时第一公民,而非测试层补丁
组合时序约束的装饰器模式
写一个高阶闭包 requireOrder(prevStage),它接收上一阶段名,返回一个装饰器闭包,包裹原始业务函数:
- 被装饰的函数执行前,先检查全局流水线状态中 lastCompleted === prevStage
- 执行后,自动设置 lastCompleted = 当前 stage
- 多个节点用同一装饰器包装,就自动形成链式时序锁:validate 用 requireOrder('init'),transform 用 requireOrder('validate'),output 用 requireOrder('transform')
- 这种写法把顺序逻辑从节点实现中剥离,复用性强,也便于统一开启/关闭校验(如测试 vs 生产)
配套日志与可观测性
每个节点闭包在执行起止时,自动向共享 trace 日志写入带序号的事件(如 "[1] validate start", "[2] validate done")。这些日志不是辅助信息,而是可断言的一等公民。
- 断言日志行数 == 预期阶段数,且每行内容严格匹配模板
- 用正则提取序号,验证是否为连续递增整数序列
- 当发现 "[3] validate done" 后紧接 "[2] transform start",就能定位到并发或重入导致的乱序,比单纯看 return 值更早暴露问题

















