面试防线:AST 执行沙箱如何处理异步逻辑与性能黑洞

面试官提问
“如果公式里需要使用 GET_USER_INFO(id) 这种需要发送网络请求的异步函数,你的基于 AST 的后序遍历执行器(Evaluator)怎么处理?因为原本同步递归的遍历遇到 Promise 会立刻断掉返回挂起状态。”

核心回答思路 (STAR法则)

  1. 业务痛点 (Situation)
    低代码平台越做越深,实施人员要求不仅能算简单的加减乘除,还能在公式里查接口、读数据库。传统的同步 AST 求值器在遇到这类异步函数时,整个执行栈会乱套,无法拿到最终聚合值。

  2. 技术考量 (Task)
    我们必须对 AST 执行器(Evaluator)进行“异步化”改造,但又要保证不影响纯同步公式的极致性能(即不能把所有的求值都强制变成耗时的 async/await)。

  3. 架构决策 (Action)

  • 支持 Promise 的混合求值策略:我在 Evaluator 内部设计了“检查点”。在计算每一个 AST Node 时,如果返回值是一个 Promise,引擎就会暂停当前同步树的求值,将其转换为异步求值链(将后续的计算包装在 .then() 中进行)。
  • 静态分析与预执行优化:为了避免把简单的 1+1 也当异步处理导致性能浪费。我在 Parser 生成 AST 树之后,增加了一层语义静态分析 (Static Analysis) 阶段。通过分析树中是否包含被标记为 isAsync: true 的系统函数节点。如果没有,就走极速的同步执行模式;如果有,再切入异步 Evaluator。
  • 并发请求打散与缓存 (Dataloader):由于公式计算往往针对表格的每一行,如果是 GET_USER_INFO,1000 行数据可能会瞬间打崩后端。我在底层沙箱的函数实现里,封装了基于 DataLoader 模式的批处理缓存:把 10ms 内的 ID 查询收集起来,合并成一个 GET_USERS_BY_IDS([id1, id2...]) 发出,彻底解决了 N+1 请求的性能黑洞。
  1. 业务价值 (Result)
    这套混合执行与智能防抖打散架构,让低代码系统的公式引擎彻底打通了和外部数据源交互的壁垒,大大拓展了低代码能做的事情边界,同时又保障了主链路的绝对高性能和后端 API 的安全。