蹦床函数本质是将递归调用转为循环以避免栈溢出,适用于长链路、多分支、状态易变的轻量级流程控制;通过统一返回结构(next/data/done/error)解耦调度与业务逻辑,支持条件跳转、状态管理与可观测性。

蹦床函数(Trampoline Function)本质是把递归调用“压平”成循环,避免栈溢出,特别适合处理长链路、条件分支多、状态易变的复杂业务流程。它不直接替代状态机或工作流引擎,但在轻量级流程控制中,能显著提升可读性和可控性。
用统一返回结构承载流程状态
每个步骤函数返回一个标准化对象,包含 next(下一个要执行的函数)、data(传递给下一步的数据)、done(是否结束)和可选的 error。这样蹦床主循环只需关注调度,不耦合业务逻辑。
- 例如:用户下单流程中,“校验库存”步骤返回
{ next: checkPayment, data: { orderId, skuId }, done: false } - 所有步骤函数签名一致:
step(context) → { next, data, done, error },便于统一编排和测试 - 错误不抛出,而是通过
error字段传递,由主循环统一捕获并触发降级或重试
把条件分支转为步骤跳转,而非嵌套 if
复杂流程常含多重判断(如“支付成功后,若用户是VIP则发双倍积分,否则发普通积分;若积分已超上限,则改发优惠券”)。与其层层嵌套,不如拆成原子步骤,用返回值决定走向。
- 把“是否VIP”、“是否超限”等判断单独写成步骤函数,返回
{ next: sendBonus, data: {...} }或{ next: sendCoupon, data: {...} } - 主蹦床循环只做一件事:取当前步骤执行结果,若
done为 true 则退出,否则将data传给next继续执行 - 流程图可直接映射为步骤函数列表,修改分支只需调整返回的
next,不碰主循环
用闭包或 context 对象管理跨步骤状态
业务数据(如订单ID、用户等级、临时计算结果)不应靠全局变量或参数层层透传。推荐两种方式:
- 轻量场景:用闭包包裹初始 context,每个步骤函数作为其内层函数访问并更新它,返回时只传增量变化
-
中大型流程:定义不可变 context 类,每步返回新实例(如
context.with({ points: 100 })),配合 TypeScript 接口约束字段,避免隐式状态污染 - 避免在步骤里直接修改原始对象,防止意外副作用;所有变更都显式体现在
data返回值中
配合日志与快照做可观测性
蹦床天然具备“单点调度”特性,非常适合注入监控。主循环每次执行步骤前后,自动记录 step 名、耗时、输入输出、是否跳过。
- 在循环入口加
log.stepStart(stepName, context),出口加log.stepEnd(stepName, result) - 关键节点(如支付、发券)失败时,把完整 context 序列化存档,用于事后回放和问题定位
- 支持按 traceId 聚合整条流程日志,无需 grep 多个服务日志,排查链路问题更直接
不复杂但容易忽略:蹦床不是万能的,它适合确定性、线性为主、偶有分支的流程;对高度并发、需外部事件驱动(如等待短信回调)、或状态持久化要求强的场景,应结合 Saga 模式或专用工作流系统。核心是让流程逻辑显性化、可追踪、易调试。











