第 11 课 · 用子流程搭建
你一直在不知不觉中建一座库。是时候调用它了。
问题
一个真正的每日例程串起你已解决的工作:回到已知界面(第 09 课)、清掉可能的弹窗(第 04 课)、收集 N 次(第 07 课)。把那些节点复制粘贴进一个巨型流程也能跑——跑一次。之后每个修复都得改三个地方。
Sub Flow(子流程)节点像调用函数一样调用一个已保存的流程:运行它、传参数、按它的结果分支。
你将学到
- 用 Sub Flow 调用流程,并按子流程的终止状态分支。
- 向子流程的 Flow Input 传参数。
- 设计带清晰契约(success/failure 的含义)的子流程。
- 读懂 Flows 界面的 Relations 列——
Uses/Used by。
开始之前
流程

徽标按阅读顺序给节点编号,与动手构建步骤对应。注意需要读的东西有多少——很少:每张 Sub Flow 卡片背后藏着一整套例程,而这正是编排器值得存在的理由。
三次 Sub Flow 调用、两个失败出口、一个成功。十六个以上的逻辑节点藏在那三张卡片背后,这块画布依然一眼可读。
动手构建
- 新建流程。从 Control 组添加一个 Sub Flow 节点;在流程选择器里挑 Lesson 09 - Recovery Routine。命名
1. Make sure we are on the dashboard。 - 第二个 Sub Flow → Lesson 04,命名
2. Clear any reward popup。 - 第三个 Sub Flow → Lesson 07,命名
3. Collect three times。在它的 Inputs 列表添加一条映射:inputtarget_count=3。该值播种进子流程的 Flow Input——不弹 Run 表单,也不用编辑子流程。 - 结局:
routine complete(success)、recovery failed(failure)、collection failed(failure)。 - 按图连线——注意弹窗步骤的两个端口都通向收集。
- Save,Auto Layout。在 Flows 界面上,Relations 列现在显示本流程 Uses 3,第 09 课则带上 Used by——库就在眼前:

契约思想
Sub Flow 调用按子流程如何结束分支——子流程的 Stop 就是它的返回值:
| 子流程终于 | 调用走 |
|---|---|
Stop: success | Success 端口 |
Stop: failure | Failure 端口 |
因此每个子流程的结局构成它的契约,父流程只是编码每份契约在此处的含义:
- 恢复失败 → 中止。 第 09 课的失败意为"不在已知界面";此时盲目收集毫无意义。失败是硬停。
- 弹窗处理"失败" → 照样前进。 最坏情形是弹窗还开着;那样收集循环会以可见的方式失败。两个端口都前进。
- 收集失败 → 上报。 例程的核心目的失败了;结局如实说出。
决定子流程的哪些失败中止父流程,是组合式自动化的大部分设计工作——而你之所以能决定,是因为每个子流程都诚实地结束。
参数。 target_count = 3 在调用时从父到子。子流程独立运行依然可用(它的 Run 表单照旧询问)、可从队列条目运行、也可被别的父流程用不同数字调用。一个流程,多个调用方——这正是 Flow Input 从第 07 课起铺垫的东西。
运行
从任意界面运行例程:
- 第 09 课不惜代价回到仪表盘(或诚实中止)。
- 第 04 课清掉可能的弹窗。
- 第 07 课点三次 Collect 并记录它的计数器。
success · Routine finished。
看运行日志:你能读出每个子流程的边界与各自的消息——组合不会藏起故事。
最佳实践
- 子流程只做一件事,用动作命名(
Recovery Routine,不是Utils)。 - 为调用方设计结局。 每个子流程至少要一个有含义的 success 和 failure。
- 逐个调用决定哪些失败中止。 没有普适规则——只有你例程的逻辑。
- 传参数,不改子流程。
- 不做复制粘贴式复用。 在流程之间复制节点,说明你需要的是 Sub Flow。
常见错误
| 错误 | 后 果 | 修复 |
|---|---|---|
| 复制节点而不是调用 | 一处修复要改 N 处 | Sub Flow |
| 无视子流程的 Failure 端口 | 父流程在失败步骤后扬长而去 | 有意识地连——即使选择是"继续",也要让它成为选择 |
| 参数名 ≠ 子流程的 input 名 | 子流程默默用默认值 | 与声明的名字精确一致 |
| 期望子流程并行 | 子流程内联、依次运行 | 并发来自实例,不来自节点 |
| 流程调用自己 | 运行时被拒绝 | 重构 |
故障排查
调用总走 Failure。 单独运行子流程。组合不改变子流程——在这里失败的,独立运行也失败。
子流程无视我的参数。
输入映射的名字必须等于子流程声明的 Flow Input 名(target_count),且子流程必须把它声明为 Input。
重命名子流程——父流程崩了吗? 没有。调用绑定流程 id;名字只是标签。
小结
- Sub Flow = 调用、传参、按结果分支,合于一个节点。
- 子流程的 Stop 是契约;父流程决定每种结局的本地含义。
- 库生长自诚实的结局 + 声明的输入——你从第 01 课就在积累的东西。
下一课
只剩一课。第 12 课 · 每日例程毕业设计组装一切——恢复、OCR、带守卫的循环、重试、计数、诚实结局——成为真实生产自动化的形态。