Electron进程间通信

在说Electron进程通信的时候,先说一下Electron中的两种进程:主进程和渲染进程。

主进程通过创建 BrowserWindow 实例来创建网页。 每一个 BrowserWindow 实例在其渲染过程中运行网页,当一个BrowserWindow 实例被销毁时,对应的渲染过程也会被终止。简单来说,一个客户端就是一个主进程。

渲染进程只能管理相应的网页,一个渲染进程的崩溃不会影响其他渲染进程。渲染进程通过 IPC 与主进程通信在网在页上执行 GUI 操作。 出于安全和可能的资源泄漏考虑,直接从渲染器进程中调用与本地 GUI 有关的 API 受到限制。简单来说,一个页面就是一个渲染进程。

注意:主进程管理所有网页及其对应的渲染进程

1. 使用IPC模块进行通信

ipcMain 模块和 ipcRenderer 是类 EventEmitter 的实例。在渲染进程中使用ipcRender模块向主进程发送消息,主进程中ipcMain接收消息,进行操作,如果还需要反馈,则通知渲染进程,渲染进程根据接收的内容执行相应的操作。

ipcMain相关文档:https://www.electronjs.org/docs/api/ipc-main

ipcRenderer相关文档:https://www.electronjs.org/docs/api/ipc-renderer

1.1 异步消息

主进程将异步消息发送回发件人,需要使用event.sender.send()

// 渲染进程中
const {ipcRenderer} = require('electron')
ipcRenderer.send('asynchronous-message', 'ping') //给Main进程发送消息 'ping'
ipcRender.on('asynchronous-reply', function (event, arg) { // 接收到Main进程返回的消息
  const message = `异步消息回复: ${arg}`
})

// 主进程中
const {ipcMain} = require('electron')
ipcMain.on('asynchronous-message',(event, arg) => { // arg为接受到的消息
  event.sender.send('asynchronous-reply', 'pong'); // 返回一个 'pong'
})

1.2 同步消息

此方法的同步特性意味着它在完成任务时会阻止其他操作,主进程回复同步信息时,需要设置event.returnValue

// 渲染进程中
const {ipcRenderer} = require('electron')

ipcRenderer.sendSync('synchronous-message', 'ping') //给Main进程发送消息 'ping'

ipcRender.on('synchronous-reply', function (event, arg) { // 接收到Main进程返回的消息
  const message = `同步消息回复: ${arg}`
})

// 主进程中
const {ipcMain} = require('electron')

ipcMain.on('synchronous-message',(event, arg) => { // arg为接受到的消息
  event.returnValue = 'pong' // 返回一个 'pong'
})

注意:切忌用 ipc 传递大量的数据,会有很大的性能问题,严重会让你整个应用卡住。

2. webContents.send方法实现通信

webcontents相关文档:https://www.electronjs.org/docs/api/web-contents

webContents.send是BrowserWindow类的一个方法。

// 主进程中
mainWindow.webContents.send('list', res.data); // mainWindow是一个BrowserWindow实例

// 渲染进程中
const {ipcRenderer} = require('electron')

ipcRenderer.on('list', (e, msg) => {
  console.log(msg);
});

3. 渲染进程之间的通信

如果数据不需要实时性,只是渲染进程之间数据的共享,可以使用localStoragesessionStorageIndexedDB,如果需要实时共享,可以利用主进程做消息中转或者利用 remote 接口直接获取渲染进程发送消息。

3.1 利用主进程把渲染进程1的消息发送给渲染进程2中

// 主进程中监听ping-event
ipcMain.on('ping-event', (event, arg) => {
  mainWindow.webContents.send('pong-event', 'something'); // mainWindow是一个BrowserWindow实例
  // 或者
  event.sender.send('pong-event', 'something');
}

// 渲染进程1
const {ipcRenderer} = require('electron')

ipcRenderer.send('ping-event', (event, arg) => {
    // do something
  }
)

// 渲染进程2
const {ipcRenderer} = require('electron')

ipcRenderer.on('pong-event', (event, arg) => {
    // do something
  }
)

3.2 使用remote或者ipcRenderer.sendTo

// 主进程
// 两个窗口互相获取对方的窗口 id, 并发送给渲染进程
win1.webContents.send('distributeIds',{
  win2Id : win2.id
});
win2.webContents.send('distributeIds',{
  win1Id : win1.id
});

// 渲染进程
// 渲染进程1通过 id 发送给渲染进程2
const {ipcRenderer} = require('electron')

remote.BrowserWindow.fromId(win2Id).webContents.send('someMsg', 'someThing');
// 或者
ipcRenderer.sendTo(win2Id, 'someMsg', 'someThing')

添加新评论