## 使用 Electron 在两个进程 (主进程和渲染进程) 之间进行通讯
通过 ipc(进程间通信)模块允许您在主进程和渲染进程之间发送和接收同步和异步消息.
这个模块有一个版本可用于这两个进程: ipcMain 和 ipcRenderer.
在浏览器中查看 [main process](http://electron.atom.io/docs/api/ipc-main) 和 [renderer proces](http://electron.atom.io/docs/api/ipc-renderer/) 的完整 API 文档.
### 异步消息
`支持: Win, macOS, Linux | 进程: Both`
使用 ipc 以异步方式在进程之间发送消息是首选方法, 因为它会在完成时返回, 而不会阻止同一进程中的其他操作.
此示例将从此进程(渲染器)发送异步消息 "Ping" 到主进程, 然后主进程回答 "Pong".
![](https://img.kancloud.cn/cd/2d/cd2de5feb4807bf1e44973bf28b079e0_809x423.png)
渲染器进程
```
sendAsyncMsg () {
const {ipcRenderer} = require('electron')
ipcRenderer.send('asynchronous-message', 'ping')
ipcRenderer.on('asynchronous-reply', (event, arg) => {
this.asyncMsg = `异步消息回复: ${arg}`
})
},
```
主进程
```
const {ipcMain} = require('electron')
ipcMain.on('asynchronous-message', (event, arg) => {
event.sender.send('asynchronous-reply', 'pong')
})
```
### 同步消息
`支持: Win, macOS, Linux | 进程: Both`
您可以使用 ipc 模块在进程之间发送同步消息. 但请注意, 此方法的同步特性意味着它在完成任务时会阻止其他操作.
此示例将从此进程(渲染器)发送同步消息 "Ping" 到主进程, 然后主进程回答 "Pong".
![](https://img.kancloud.cn/c2/69/c269fc70ce1f09a5d50c8038bfc7dfc9_789x236.png)
渲染器进程
```
sendSyncMsg () {
const {ipcRenderer} = require('electron')
const reply = ipcRenderer.sendSync('synchronous-message', 'ping')
this.syncMsg = `同步消息回复: ${reply}`
},
```
主进程
```
const {ipcMain} = require('electron')
ipcMain.on('synchronous-message', (event, arg) => {
event.returnValue = 'pong'
})
```
### 与隐藏窗口通信
通常的做法是创建一个新的不可见浏览器窗口(渲染器进程), 以便在不影响主应用程序窗口中的性能的情况下运行任务.
在这个示例中, 我们使用 <code>remote</code> 模块从这个渲染器进程创建一个新的不可见的浏览器窗口. 当新页面加载时, 我们用 <code>ipc</code> 发送一个消息给正在监听的新窗口.
然后新窗口计算阶乘并发送要由此接收的结果到原始窗口并添加到上面的页面中.
![](https://img.kancloud.cn/73/06/73067a4769ce318c051afe9bac857910_747x415.png)
渲染器进程
```
cumInvisible () {
const {BrowserWindow} = require('electron').remote
const ipcRenderer = require('electron').ipcRenderer
const windowID = BrowserWindow.getFocusedWindow().id
let invisPath
if (process.env.NODE_ENV === 'development') {
invisPath = 'http://localhost:8080#/invisibleWin'
} else {
invisPath = `file://${__dirname}/index.html#/invisibleWin`
}
const win = new BrowserWindow({
width: 400,
height: 400,
show: false,
webPreferences: {
nodeIntegration: true
}
})
win.loadURL(invisPath)
win.webContents.on('did-finish-load', () => {
const input = 100
win.webContents.send('compute-factorial', input, windowID)
})
ipcRenderer.on('factorial-computed', (event, input, output) => {
this.inMsg = `${input} 的阶乘是 ${output}`
})
}
```
隐藏窗口脚本
```
const ipc = require('electron').ipcRenderer
const BrowserWindow = require('electron').remote.BrowserWindow
ipc.on('compute-factorial', function (event, number, fromWindowId) {
const result = factorial(number)
const fromWindow = BrowserWindow.fromId(fromWindowId)
fromWindow.webContents.send('factorial-computed', number, result)
console.log(result)
window.close()
})
function factorial (num) {
if (num === 0) return 1
return num * factorial(num - 1)
}
```