docs: add async browser script support design

Design for fixing Promise serialization issue in build_eval_js.
Async functions return Promise which gets JSON.stringify'd to "{}".

🤖 Generated with [Qoder][https://qoder.com]
This commit is contained in:
木炎
2026-04-13 16:06:41 +08:00
parent a957712590
commit ce6b3e6749

View File

@@ -0,0 +1,69 @@
# 异步 Browser Script 支持设计
## 问题
`collect_lineloss.js``buildBrowserEntrypointResult` 是 async 函数,但 `build_eval_js` 生成的执行代码是同步的,导致 Promise 被 JSON.stringify 序列化为 `{}`
**日志表现**
```
[execute_browser_script_impl] 返回成功, payload 长度: 4
```
返回 `{}(4字符)` 而不是实际的报表数据。
## 根本原因
`callback_backend.rs``build_eval_js` 函数:
```javascript
var v=(function(){return {script}})(); // 同步执行
var t=(typeof v==='string')?v:JSON.stringify(v); // Promise -> "{}"
```
当 script 返回 Promise 时,`JSON.stringify(Promise)` 返回 `{}`
## 解决方案
修改 `build_eval_js` 支持 Promise
1.`await` 等待 script 执行结果
2. 检测结果是否为 Promise如果是则等待 resolve
3. 保持对同步脚本的向后兼容
## 实现细节
修改 `src/browser/callback_backend.rs``build_eval_js` 函数:
```javascript
(async function(){
try {
var v = await (function(){return {script}})();
// 等待 Promise resolve
if (v && typeof v.then === 'function') {
v = await v;
}
var t = (typeof v === 'string') ? v : JSON.stringify(v);
// ... 回调逻辑保持不变
} catch(e) {}
})()
```
关键点:
- 包装整个 IIFE 为 async
-`await` 等待 script 执行
- 检测 Promise-like 对象 (`v.then === 'function'`)
- 向后兼容同步脚本直接返回值async 脚本返回 Promise 后被 await
## 影响范围
- `src/browser/callback_backend.rs`: 修改 `build_eval_js` 函数
- 所有 `browser_script` 类型的 skill 自动支持 async
## 测试验证
1. 运行 `cargo test` 确保现有测试通过
2. 端到端测试 `tq-lineloss-report.collect_lineloss` 返回实际数据而非 `{}`
3. 验证同步脚本(如知乎热榜)仍然正常工作
## 不在范围内
- 不修改 `wrap_browser_script`(方案 C 的做法)
- 不修改 skill 脚本本身