生成器可通过命令模式+状态快照实现可中断、可回退、可重入的执行流:每步封装为含execute()/undo()的命令对象,生成器仅调度节奏;暂停时闭包保留上下文,外部栈管理撤销;return值传递终态摘要。

生成器本身不直接支持“撤销步骤挂起”,但可以借助其暂停/恢复能力 + 命令模式 + 状态快照机制,构造出具备可中断、可回退、可重入特性的逻辑执行流。关键不是让 yield 自动倒带,而是把每一步操作封装为可逆单元,并用生成器控制其执行节奏。
用生成器驱动命令序列的执行节奏
生成器作为“执行调度器”,不直接处理业务逻辑,而是按需触发命令对象的 execute() 或 undo() 方法:
- 每次调用
next(),生成器 yield 出下一个待执行的命令对象(或其元信息) - 外部调用方决定是执行它(
command.execute())、跳过它,还是反向执行它(command.undo()) - 生成器内部不保存状态变更,只维护当前执行位置和上下文索引
每步操作必须自带“正向+逆向”能力
仅靠 yield 暂停不够,撤销依赖的是命令对象自身的可逆设计:
- 定义
Command接口:含execute(): void和undo(): void - 例如
MoveNodeCommand需记录移动前坐标(oldPos)和移动后坐标(newPos),undo 时还原oldPos - 生成器遍历时,每个
yield command提供的是完整可逆动作,而非原始数据
挂起期间保留执行上下文与回退锚点
生成器暂停时,局部变量(如计数器、临时缓存、上一步结果)仍保留在闭包中,这天然支持“挂起后继续”:
- 在生成器函数内维护
lastResult或stepIndex,用于衔接后续操作 - 配合外部栈结构(如
undoStack),在每次execute()后将命令推入,实现“挂起即已记录” - 若中途需要撤销,不重启生成器,而是从栈中取出上一命令调用
undo(),再调整生成器的消费位置(例如用generator.return()跳转或重新实例化)
利用 return 值传递流程终态(增强挂起语义)
生成器结束时的 return 值可作为整个流程的摘要反馈,尤其适合“挂起后确认完成”的场景:
- 例如工作流生成器执行到最后一步,
return { status: 'completed', summary: { totalSteps: 5, failed: 0 } } - 外部可通过
generator.getReturn()(PHP)或捕获done === true && value(JS)获取该终态 - 这使“挂起”不仅是暂停,还能携带阶段成果,为下一步决策提供依据










