Electron 耗时任务与性能排查

识别主进程阻塞,使用合适的后台任务方式,并掌握基础的资源清理方法。

🎯 引言

Electron 的窗口和系统操作都依赖应用的进程。如果在主进程里连续处理大量数据,窗口可能暂时没有响应。本篇先学会判断问题,再了解 Worker 和 utilityProcess 的基本分工。


🧱 不要阻塞主进程

下面的同步循环会占用主进程:

function doWork() {
    for (let index = 0; index < 1000000000; index += 1) {
        // 计算任务
    }
}

只要循环没有结束,主进程就很难及时处理窗口事件。文件操作优先使用 node:fs/promises 的异步 API,复杂计算则应移动到后台任务。


🛠 选择后台任务方式

任务适合方式
页面中的计算Web Worker
主进程中的 JavaScript 计算utilityProcess 或 Node.js Worker
调用独立命令行工具child_process
大文件读取异步文件 API 或 Stream

初学时不需要同时学习所有方案。先把“是否会长时间占用当前进程”作为判断标准。


🧹 清理窗口和监听器

窗口关闭后,定时器、事件监听器和文件句柄仍然可能继续工作:

const timer = setInterval(() => {
    console.log('检查任务状态');
}, 5000);

win.on('closed', () => {
    clearInterval(timer);
});

创建一个资源,就要考虑什么时候释放它。多次创建窗口时尤其要注意,不能每次都重复注册同一个全局监听器。


🔍 从现象定位问题

可以按下面顺序排查:

  1. 页面是否只是单个按钮没有响应,还是整个窗口都卡住?
  2. 主进程是否正在执行同步循环或同步文件操作?
  3. 是否重复注册监听器或定时器?
  4. 是否在窗口关闭后仍然持有大对象?
  5. 开发者工具的 Performance 和 Memory 面板是否显示异常?

先确认问题类型,再选择工具,不要一开始就盲目更换线程方案。


🧾 小节总结

  • 主进程不适合执行长时间同步计算。
  • 异步文件 API 可以减少等待造成的卡顿。
  • Worker、utilityProcess 和子进程适合不同任务。
  • 窗口关闭时要清理定时器、监听器和资源。
  • 排查性能要先观察现象,再定位具体进程。

❓ 知识问答

Q1:使用 async/await 就一定不会卡顿吗?

A:不一定。await 只能等待异步操作,长时间同步计算仍然会阻塞当前进程。

Q2:为什么窗口关闭后还要清理定时器?

A:定时器可能继续执行并保留对象引用,造成无意义的工作和内存占用。

🧪 小练习

找出下面代码中可能阻塞主进程的部分,并改成异步文件读取:

// 请在这里编写代码

🎉 现在你已经掌握了 Electron 性能排查的基本思路。