electron
是nodejs
+chrome内核
+native层
的集成,类似chrome
浏览器每个页面都属于一个进程(称为渲染进程),另外还有主进程,其提供了如下进程间通信机制:
- IPCMain IPCRender通信模块,其中IPCMain用于主进程,IPCRender用于渲染进程,这两者都是node's EventEmiter实例的封装;
-
渲染进程->主进程
渲染进程通过IPCRender.send发送异步消息,IPCRender.sendSync发送同步消息;主进程通过IPCMain.on接收消息并通过event.sender.send响应异步消息,event.returnValue响应同步消息。
通过IPCMain与IPCRender模块可实现client-server模型,主进程作为server端注册消息并提供业务服务(如创建窗口、托盘、数据持久化访问及设置等),渲染进程作为client端以发送消息,因此可建立消息与业务的分离,业务层注册可实现的消息并处理响应结果及返回数据;
// In main process.
const {ipcMain} = require('electron')
ipcMain.on('asynchronous-message', (event, arg) => {
console.log(arg) // prints "ping"
event.sender.send('asynchronous-reply', 'pong')
})
ipcMain.on('synchronous-message', (event, arg) => {
console.log(arg) // prints "ping"
event.returnValue = 'pong'
})
// In renderer process (web page).
const {ipcRenderer} = require('electron')
console.log(ipcRenderer.sendSync('synchronous-message', 'ping')) // prints "pong"
ipcRenderer.on('asynchronous-reply', (event, arg) => {
console.log(arg) // prints "pong"
})
ipcRenderer.send('asynchronous-message', 'ping')
主进程->渲染进程
主进程通过BrowserWindow.webcontent.send发送消息,通过在主进程管理所有窗口对象,可遍历所有窗口对象的webcontent属性来发送消息,进而可实现主进程向渲染进程的广播消息
注意,
webContents.on
监听的是已经定义好的事件,如上面的did-finish-load
。要监听自定义的事件还是通过ipcMain
和ipcRenderer
。渲染进程的监听事件回调函数中,也可以通过
event.sender
来向主进程发送消息。这个对象只是ipcRenderer
的引用(event.sender === ipcRenderer)。因此,event.sender
发送的消息在主进程中还是需要通过ipcMain.on
方法来监听,而不是通过webContents.on
方法。
-
// In the main process. const {app, BrowserWindow} = require('electron') let win = null 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('ping', 'whoooooooh!') }) })
<!-- index.html --> <html> <body> <script> require('electron').ipcRenderer.on('ping', (event, message) => { console.log(message) // Prints 'whoooooooh!' }) </script> </body> </html>
- electron.remote模块
渲染进程可加载remote模块,并访问主进程的模块或者app对象,从而使用主进程的模块或者获取变量,如BrowserWindow、global对象。
进程间通信机制封装
可通过electron
提供的通讯机制接口封装一套通讯模块,用于主进程与渲染进程间通信,基于client-server
、订阅/发布
及广播
模型构建一套完成的进程间消息机制,消息机制流程(可参考)如下:
渲染进程加载本地js文件
渲染进程需要加载本地的IPC Client
js文件已实现进程间通信,可通过如下方式实现:
使用browserwindow.webPreferences.preload指定需要加载的js文件
使用browserwindow.webcontent.executejavascript()接口
使用executejavascript
方式存在时序问题,因其加载晚于webcontent加载渲染页面,而preload
方式要早于webcontent页面加载;
BrowserWindow对象都有唯一的窗口ID(可通过getCurrentWindow来获取),若是基于业务需要设置绑定不同的ID,可通过此唯一的ID绑定需要设置的ID,并通过remote模块获取对应关系,以解决BrowserWindow对象通过executejavascript时序问题;