try-catch仅能捕获js主线程同步异常,无法拦截原生进程崩溃、子进程退出、ipc超时、gpu异常等底层错误;需分层构建js异步兜底、进程生命周期监听、子进程状态审计、ipc双向确认四类机制,并辅以带traceid和环境快照的结构化日志。

try-catch 本身无法“全量拦截”跨端桌面应用中的原生底层进程错误——它不是万能兜底开关,而是一个有明确作用边界的同步异常捕获机制。真正能被它捕获的,仅限于 JavaScript 主线程中同步抛出的异常(如 throw new Error()、JSON.parse('{'、undefined.xxx 等运行时 TypeError)。原生进程崩溃、子进程 exit code、IPC 通信超时、Node.js 原生模块 segfault、GPU 渲染线程卡死等,完全不在其覆盖范围内。
哪些错误 try-catch 根本捕不到
这些常见底层问题,外层 try-catch 写得再密也无济于事:
-
子进程异常退出:比如
spawn('ffmpeg', [...])崩溃,只会触发childProcess.on('exit', (code, signal) => {...}),不会抛 JS 异常 - Node.js 原生模块崩溃:C++ 插件内存越界、V8 堆溢出、libuv 底层断言失败,直接终止进程,不经过 JS 异常流
-
IPC 通道断裂:主进程与渲染进程间
ipcRenderer.send()失败(如对方已销毁),只返回false或触发once('render-process-gone'),不 throw -
GPU/硬件加速异常:WebGL context lost、DirectX 初始化失败,触发
webglcontextlost事件,而非同步异常 -
系统级资源拒绝:文件句柄耗尽、内存分配失败(
ENOMEM)、权限不足(EACCES),通常以 callback 参数或 Promise reject 形式返回,需显式判断
真正有效的“全量审计”要分层建设
不是靠一层 try-catch,而是组合使用四类机制,覆盖不同错误层级:
一款AI图像与设计工具,主要用于将文本渲染为图片并返回临时本地文件路径,支持可选的 data URI。适用于 Clawhub 或 Codex,用于将纯文本或带样式的文本进行转换,适合需要提升相关任务效率的用户。
-
JS 层异步操作兜底:所有
await的 Promise 必须包裹在 async 函数的 try-catch 中;对childProcess.spawn、fs.promises.readFile、ipcRenderer.invoke等调用,统一用try { const res = await op() } catch (e),并记录e.stack和操作上下文(如命令行参数、文件路径) -
进程级生命周期监听:在主进程中监听
app.whenReady()后注册:process.on('uncaughtException', logAndReport)process.on('unhandledRejection', (reason) => logAndReport(reason))app.on('render-process-gone', (e, webContents, details) => {...}) -
原生子进程状态审计:对每个 spawn 的子进程,绑定完整事件链:
proc.on('error', e => audit('spawn-error', { cmd, e }))proc.on('exit', (code, signal) => audit('proc-exit', { cmd, code, signal }))proc.stderr.on('data', chunk => audit('proc-stderr', { cmd, chunk })) -
IPC 通信双向确认机制:不依赖单次
invoke,改用带超时和重试的封装:async function safeInvoke(channel, ...args) {<br> const timeout = setTimeout(() => reject(new Error('IPC timeout')), 5000);<br> try { return await ipcRenderer.invoke(channel, ...args); }<br> finally { clearTimeout(timeout); }<br>}
并在主进程 handler 中加try/catch + auditLog
审计日志必须包含可追溯的上下文字段
单纯捕获错误堆栈没用,关键是要让每条日志能反向定位到具体用户行为和环境状态:
- 统一注入 traceId(从主窗口创建时生成,透传至所有子进程和 IPC 调用)
- 记录进程角色(main / renderer / worker / ffmpeg-child)和 PID
- 标注触发动作(如 “点击导出按钮 → spawn ffmpeg → 解码 MP4”)
- 附带环境快照:Electron 版本、OS 架构、可用内存、GPU 型号(通过
app.getGPUInfo('complete')) - 对原生错误,优先解析
errno或exitCode,而非只记字符串消息(例如code === 137比"Killed"更能指向 OOM)
不要混淆“捕获”和“恢复”
多数原生底层错误不可恢复——子进程崩溃后不能自动重启而不丢状态,GPU 上下文丢失后无法原样还原画面。此时 try-catch 的作用不是“修复”,而是:
- 阻止错误蔓延(避免渲染进程整个白屏)
- 触发降级策略(如切换软件解码、禁用硬件加速)
- 生成结构化审计事件(含时间戳、traceId、错误分类码),供后台聚类分析
- 向用户展示明确提示(如“视频编码失败,请检查磁盘空间”而非“未知错误”)










