Writing Assistance API 中关于中止信号同步拒绝的设计考量
在 Web 机器学习领域的 Writing Assistance API 开发过程中,关于中止信号(AbortSignal)处理机制的设计引发了一个值得探讨的技术决策:当调用中止操作时,是否应该同步拒绝返回的 Promise。
核心问题背景
现代 Web API 设计中普遍采用 AbortController/AbortSignal 模式来提供异步操作的中止能力。Writing Assistance API 的 create() 方法同样实现了这一机制,允许开发者通过 signal 参数控制异步创建过程的终止。
最初实现采用了异步拒绝模式:当中止信号触发时,通过设置一个标志变量(abortDuring*),由后台并行进程排队执行 Promise 的拒绝操作。这种设计带来了一个微妙的时序问题:当开发者同时使用 Promise.race() 组合多个 Promise 时,中止拒绝的时序会影响最终结果。
同步 vs 异步拒绝的差异
通过代码示例可以清晰展示两种模式的差异:
const controller = new AbortController();
const create_promise = AiAPI.create({signal: controller.signal}));
controller.abort();
// 结果取决于拒绝的时序:
Promise.race([Promise.reject(), create_promise]);
在同步拒绝模式下,create_promise 的拒绝会立即执行,通常会在竞速中胜出;而异步拒绝模式下,外部的 Promise.reject() 通常会先被执行。
技术实现考量
最初的设计考虑主要基于两个检查点:
- 在 create() 方法的同步执行体中检查中止信号
- 在后台并行处理过程中检查中止状态
这种设计看似完整,但实际上遗漏了信号监听器触发时的即时响应能力。经过深入讨论,团队意识到可以在信号的中止步骤中直接添加拒绝逻辑,而不仅限于设置标志变量。
行业实践参考
经过调研发现,类似 fetch() API 等 Web 标准接口采用了同步拒绝模式。这种模式具有以下优势:
- 提供更可预测的行为时序
- 与开发者对"立即中止"的心理模型更吻合
- 避免微妙的竞态条件
最终决策
基于这些分析,Writing Assistance API 决定采用同步拒绝模式来响应中止信号。这一变更使得 API 行为更加符合开发者预期,也与其他 Web 标准保持了一致性。对于实现者而言,这意味着需要在中止信号的监听回调中直接执行 Promise 的拒绝操作,而不仅是通过标志变量间接触发。
这一设计决策体现了 API 设计中时序一致性的重要性,也展示了 Web 平台 API 如何通过借鉴现有模式来提供更符合直觉的开发者体验。
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考