electron
是nodejs
+chrome內(nèi)核
+native層
的集成,類似chrome
瀏覽器每個頁面都屬于一個進程(稱為渲染進程)叽躯,另外還有主進程,其提供了如下進程間通信機制:
- IPCMain IPCRender通信模塊肌括,其中IPCMain用于主進程点骑,IPCRender用于渲染進程,這兩者都是node's EventEmiter實例的封裝谍夭;
-
渲染進程->主進程
渲染進程通過IPCRender.send發(fā)送異步消息黑滴,IPCRender.sendSync發(fā)送同步消息;主進程通過IPCMain.on接收消息并通過event.sender.send響應(yīng)異步消息紧索,event.returnValue響應(yīng)同步消息袁辈。
通過IPCMain與IPCRender模塊可實現(xiàn)client-server模型,主進程作為server端注冊消息并提供業(yè)務(wù)服務(wù)(如創(chuàng)建窗口珠漂、托盤晚缩、數(shù)據(jù)持久化訪問及設(shè)置等),渲染進程作為client端以發(fā)送消息媳危,因此可建立消息與業(yè)務(wù)的分離荞彼,業(yè)務(wù)層注冊可實現(xiàn)的消息并處理響應(yīng)結(jié)果及返回數(shù)據(jù);
// 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發(fā)送消息待笑,通過在主進程管理所有窗口對象鸣皂,可遍歷所有窗口對象的webcontent屬性來發(fā)送消息,進而可實現(xiàn)主進程向渲染進程的廣播消息
注意暮蹂,
webContents.on
監(jiān)聽的是已經(jīng)定義好的事件寞缝,如上面的did-finish-load
。要監(jiān)聽自定義的事件還是通過ipcMain
和ipcRenderer
仰泻。渲染進程的監(jiān)聽事件回調(diào)函數(shù)中荆陆,也可以通過
event.sender
來向主進程發(fā)送消息。這個對象只是ipcRenderer
的引用(event.sender === ipcRenderer)集侯。因此被啼,event.sender
發(fā)送的消息在主進程中還是需要通過ipcMain.on
方法來監(jiān)聽帜消,而不是通過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
、訂閱/發(fā)布
及廣播
模型構(gòu)建一套完成的進程間消息機制勘伺,消息機制流程(可參考)如下:
渲染進程加載本地js文件
渲染進程需要加載本地的IPC Client
js文件已實現(xiàn)進程間通信跪腹,可通過如下方式實現(xiàn):
使用browserwindow.webPreferences.preload指定需要加載的js文件
使用browserwindow.webcontent.executejavascript()接口
使用executejavascript
方式存在時序問題,因其加載晚于webcontent加載渲染頁面飞醉,而preload
方式要早于webcontent頁面加載冲茸;
BrowserWindow對象都有唯一的窗口ID(可通過getCurrentWindow來獲取)缅帘,若是基于業(yè)務(wù)需要設(shè)置綁定不同的ID轴术,可通過此唯一的ID綁定需要設(shè)置的ID,并通過remote模塊獲取對應(yīng)關(guān)系钦无,以解決BrowserWindow對象通過executejavascript時序問題逗栽;