electron进程间通信

  • 邢毅彪
  • 9 Minutes
  • 2018年10月13日

前言

最近公司在开发一个基于electron的客户端, 之前没有接触过electron, 刚好趁此机会算是一个总结吧。

electron里面的进程

electron常规拥有两个进程:主进程(main)、渲染进程(render)。
主进程为package.json里面main脚本的进程,而渲染进程是主进程使用 BrowserWindow 实例创建页面。 每个 BrowserWindow 实例都在自己的渲染进程里运行页面。 当一个 BrowserWindow 实例被销毁后,相应的渲染进程也会被终止。

主进程与渲染进程的区别

  1. 主进程是管理所有的web渲染进程,且唯一。渲染进程只关注自己渲染的web页面,且独立。
  2. 渲染进程不允许调用GUI相关的原生api, 如果要调用必须与主进程通信, 利用主进程的能力调用。

主进程与渲染进程如何通信

electron提供了很多主进程与渲染进程通信的方法:如主进程使用ipcMain,渲染进程使用ipcRenderer方法相互通信。也可以渲染进程使用remote模块直接调用主进程方法进行通信。本次将介绍这两种进程间通信的方法。

  1. 使用remote方法通信
1
2
3
4
5
6
// main.js
let msg = ''

function changeMsg(m) {
msg = m
}
1
2
3
4
// render.js
const changeMsg = require('electron').remote.getGlobal(changeMsg)

changeMsg('hello I`m render')

上例近演示调用main进程全局方法进行通信, 类似回调句柄转换通信。remote模块提供我们四个方法require()(获得相对main脚本路径的引入)、getCurrentWindow()(获得渲染进程当前窗口)、getCurrentWebContents()(获得渲染进程当前内容)、getGlobal(name)(获得主进程对应name的属性、方法)remote方法本身会返回主进程的electron对象本身,因此具有此对象所有方法和能力。

  1. 使用ipcMain和ipcRenderer

首先这两个模块本身是一个EventEmitter类的实例,这意味着其拥有EventEmitter的所有方法,包括addEventListener和removeEventListener等方法。这里仅演示发送同步和异步事件,以及主进程主动向渲染进程推送事件。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// main.js
const { app, BrowserWindow, ipcMain } = require('electron')
// 异步返回演示
ipcMain.on('asynchronous-message', (evt, msg) => {
console.log(msg) // 打印 "ping"

// 此处使用渲染进程句柄发送异步事件给渲染进程
evt.sender.send('asynchronous-reply', 'pong')
})

// 同步返回演示
ipcMain.on('synchronous-message', (evt, msg) => {
console.log(msg) // 打印 "ping"
evt.returnValue = 'pong'
})

// 主进程主动向渲染进程推送事件
app.on('ready', () => {
win = new BrowserWindow({width: 800, height: 600})
win.loadURL(`file://${__dirname}/index.html`)
win.webContents.on('did-finish-load', () => {
// 主动推送事件到渲染进程
win.webContents.send('main-push-msg', 'whoooooooh!')
})
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// 渲染进程
const {ipcRenderer} = require('electron')

// 发送同步事件返回值
let sendSyncReturnMsg = ipcRenderer.sendSync('synchronous-message', 'ping')
console.log(sendSyncReturnMsg) // 打印 "pong"

// 监听异步事件
ipcRenderer.on('asynchronous-reply', (evt, msg) => {
console.log(msg) // 打印 "pong"
})

// 发送异步事件
ipcRenderer.send('asynchronous-message', 'ping')

// 监听主进程主动推送事件
ipcRenderer.on('main-push-msg', (evt, msg) {
console.log(msg) // 打印 "whoooooooh!"
})

至此electron中main线程与render线程通信常用方法已介绍完毕。

访问量