- Published on
Electron 进程通信:主进程和渲染进程的对话
- Authors
- Name
- Violet Chen
Electron 的进程通信(IPC)是开发桌面应用的核心,主进程和渲染进程各司其职,IPC 就是它们之间的“电话线”。这篇聊聊 IPC 的实现和优化。
主进程和渲染进程啥区别?
主进程跑 Node.js,负责系统级操作,比如文件读写、窗口管理。渲染进程跑 Chromium,处理 UI 和 DOM 操作。两者不能直接互访,IPC 提供了一个安全通道。
用 electron
的 ipcMain
和 ipcRenderer
模块来实现通信。主进程监听事件,渲染进程发送消息,简单又高效。
基础 IPC 实现
假设我们要写个桌面应用,渲染进程点按钮,触发主进程查系统信息(比如 CPU 使用率),然后返回给 UI 显示。
主进程代码
在 main.js
中设置监听:
const { app, BrowserWindow, ipcMain } = require('electron')
const os = require('os')
app.whenReady().then(() => {
const win = new BrowserWindow({
webPreferences: {
contextIsolation: true, // 安全隔离
preload: `${__dirname}/preload.js`, // 预加载脚本
},
})
win.loadFile('index.html')
// 监听渲染进程的消息
ipcMain.handle('get-cpu-usage', async () => {
const cpu = os.cpus()
return cpu[0].times // 返回 CPU 时间信息
})
})
预加载脚本
在 preload.js
中暴露安全的 API:
const { contextBridge, ipcRenderer } = require('electron')
contextBridge.exposeInMainWorld('api', {
getCpuUsage: () => ipcRenderer.invoke('get-cpu-usage'),
})
渲染进程代码
在 React(或其他前端框架)里调用:
// renderer.js 或 React 组件
async function fetchCpuUsage() {
const cpuData = await window.api.getCpuUsage()
console.log(cpuData) // 渲染到 UI
}
// JSX 示例
;<button onClick={fetchCpuUsage}>查 CPU</button>
两种 IPC 模式
异步通信(
invoke
/handle
):像上面例子,适合需要返回值的场景。ipcRenderer.invoke
返回 Promise,方便处理异步操作。同步通信(
send
/on
):适合简单通知:// 渲染进程 ipcRenderer.send('show-notification', '任务完成!') // 主进程 ipcMain.on('show-notification', (event, message) => { new Notification({ title: '提示', body: message }).show() })
invoke
/handle
更现代,推荐优先使用,因为它支持错误处理和异步逻辑。
优化技巧
安全第一:
- 启用
contextIsolation: true
,避免渲染进程直接访问 Node.js API。 - 用预加载脚本(
preload.js
)通过contextBridge
暴露最小化 API,防止 XSS 攻击。
contextBridge.exposeInMainWorld('api', { safeFunction: () => ipcRenderer.invoke('safe-action'), })
- 启用
性能优化:
- 避免频繁 IPC 调用,合并请求。比如,批量获取系统数据:减少通信次数,降低 10% 的进程间开销(Node.js 性能分析)。
// 主进程 ipcMain.handle('get-system-info', async () => { return { cpu: os.cpus(), memory: os.freemem(), } })
- 用事件节流处理高频交互:
// 渲染进程 import { throttle } from 'lodash' const throttledSend = throttle(() => { ipcRenderer.send('update-data', data) }, 1000)
- 避免频繁 IPC 调用,合并请求。比如,批量获取系统数据:
错误处理:
- 在
handle
中捕获异常:ipcMain.handle('fetch-data', async () => { try { return await complexOperation() } catch (error) { throw new Error(`操作失败: ${error.message}`) } })
- 渲染进程检查错误:
try { const data = await window.api.getData() } catch (error) { console.error('IPC 错误:', error) }
- 在
调试技巧
- 用 Electron 的
--inspect
调试主进程:在 Chrome 打开electron --inspect=5858 .
chrome://inspect
连接调试。 - 检查 IPC 消息用
electron-log
:const log = require('electron-log') ipcMain.on('log-event', (event, msg) => log.info(msg))
总结
Electron 的 IPC 让主进程和渲染进程配合得像好搭档,异步 invoke
/handle
适合复杂交互,send
/on
适合简单通知。安全配置和性能优化是关键,特别是 contextIsolation
和批量通信。