"Export notes(导出笔记)"去哪儿了?
本指南使用一个小型 Electron 应用。点击Export notes(导出笔记)后,页面调用 API,通过进程边界进入主进程,最后写出 CSV。这个行为分散在几个文件中。
跨 Electron 进程的 CSV 导出
-
渲染进程 → preload
notes.exportCsv()renderer.js调用preload.js暴露的 API。 -
进程之间
notes:exportpreload 调用一条 IPC 通道——即发往主进程的一条具名消息。 -
主进程导出处理函数
main.js处理这个通道,再调用 CSV 写入函数。
csv.js 格式化笔记 → main.js 写入 downloads/notes.csv。
询问有关 CSV 导出
将你的编程助手连接到 REA,并把应用目录或 ASAR 文件路径给它:
用 REA 找出这个应用导出笔记时发生了什么。CSV 文件在哪里创建?
示例提示。 包括应用程序文件夹的绝对路径或 app.asar.
REA 读取应用文件,构建入口点、模块和进程边界的映射。你的编程助手用这张图把调查范围收窄到导出功能。
跟踪导出代码
页面调用一个小API
document.querySelector("#export").addEventListener("click", async () => {
const destination = await window.notes.exportCsv();
document.querySelector("#status").textContent = `Saved to ${destination}`;
});
页面知道方法名称。 实现存在于预加载中,预加载将其暴露给渲染器。
contextBridge.exposeInMainWorld("notes", {
exportCsv: () => ipcRenderer.invoke("notes:export"),
});
REA 记录 notes.exportCsv 和直接写在代码中的通道名 notes:export,并将调用关联到主进程里唯一匹配的处理函数。
ipcMain.handle("notes:export", () => {
const destination = path.join(app.getPath("downloads"), "notes.csv");
writeFileSync(destination, toCsv(notes), "utf8");
return destination;
});
读取处理函数就能回答最初的问题:csv.js 格式化笔记,主进程将 notes.csv 写入用户的下载文件夹。
{
"literal_channels": 1,
"renderer_transmissions": 1,
"main_handlers": 1,
"paired_renderer_transmissions": 1,
"ambiguous_renderer_transmissions": 0
}
使用 REA 4.1.0 分析下面可下载的示例。API、通道和处理函数的结果均附有源码位置。
自己分析例子
下载示例并解压。压缩包内含完整的 notes-example 文件夹。用 Node.js 和 npm 分析它;本例不需要 Electron。
npx -y rea-agents@latest analyze-javascript-application \
/absolute/path/to/notes-example --json
将路径替换为你解压缩的文件夹。 你应该在以下位置找到一个IPC通道和一个匹配的处理程序 normalized_result.summary.ipc. 源位置在 normalized_result.graph.
对于你自己的应用,用相同的命令加上它的目录或 ASAR 路径。编程助手可以用 REA 的功能追踪工具追踪字面字符串、API 名称或 IPC 通道。
检查CSV写入器
追踪
notes:export到处理函数。哪些输入传给 CSV 写入函数?如果写入失败,会怎样?
使用源位置检查这些详细信息。 计算的通道名称和不明确的处理程序可以保持未解析;运行时观察为你提供了另一种调查它们的方法。
- 追踪 Notion 剪贴板桥接代码把同样的方法用于打包的 Electron 应用。
- 观察浏览器导出捕获一次真实点击,看看它发起了哪个请求。
- 追踪一个原生函数当某项功能依赖原生代码时,继续进入二进制文件。