electron開發入門(二)程式通訊
目錄
- 主程式與渲染程式
- 主程式與渲染程式之間的通訊
1. 主程式與渲染程式
在 electron 中,最重要的一個概念就是主程式和渲染程式。
1.1 主程式
main.js在啟動應用後就建立了一個主程式-main process,它可以通過electron中的一些模組直接與原生GUI(在你的應用視窗)互動。
1.2 渲染程式
僅啟動主程式並不能給你的應用建立應用視窗。視窗是通過main檔案裡的主程式呼叫叫BrowserWindow的模組建立的。
上述示例中的index.html頁面,是主程式建立了一個渲染程式視窗所載入的Web頁面,每個頁面都是執行在自己的程式裡,這些程式我們稱之為渲染程式。
渲染程式會在視窗中渲染出web頁面(引用了CSS,JavaScript,圖片等的HTML檔案)。web頁面是Chromium渲染的,因為各系統下標準是統一的的,所以相容性很好。
1.3 主程式與渲染程式的關係
主程式通過構造BrowserWindow例項來建立頁面。每個 BrowserWindow例項都在自己的渲染程式裡執行頁面。當一個 BrowserWindow 例項被銷燬後,相應的渲染程式也會被終止。
主程式管理所有頁面和與之對應的渲染程式。每個渲染程式都是相互隔離的,並且只知道執行在該程式裡的頁面。
在頁面裡呼叫本地GUI是不允許的,因為在Web頁面裡管理本地GUI資源是非常危險而且容易造成資源洩露。如果你想在網頁裡進行GUI操作,該頁面的渲染程式必須與主程式進行通訊,請求主程式進行相關的 GUI 操作。
2. 主程式與渲染程式之間的通訊
在electron中,主程式與渲染程式有很多通訊的方法。比如ipcRenderer和ipcMain,還可以在渲染程式使用remote模組。
2.1 ipcMain & ipcRenderer
- 主程式:ipcMain
- 渲染程式:ipcRenderer
ipcMain模組和ipcRenderer是類EventEmitter的例項。
在主程式中使用ipcMain接收渲染執行緒傳送過來的非同步或同步訊息,傳送過來的訊息將觸發事件。
在渲染程式中使用ipcRenderer向主程式傳送同步或非同步訊息,也可以接收到主程式的訊息。
- 傳送訊息,事件名為 channel .
- 迴應同步訊息, 你可以設定 event.returnValue .
- 迴應非同步訊息, 你可以使用 event.sender.send(...)
下面給出一個簡單例子:
// In main process.
const ipcMain = require('electron').ipcMain;
ipcMain.on('asynchronous-message', function(event, arg) {
console.log(arg); // prints "ping"
event.sender.send('asynchronous-reply', 'pong');
});
ipcMain.on('synchronous-message', function(event, arg) {
console.log(arg); // prints "ping"
event.returnValue = 'pong';
});
// In renderer process (web page).
const ipcRenderer = require('electron').ipcRenderer;
console.log(ipcRenderer.sendSync('synchronous-message', 'ping')); // prints "pong"
ipcRenderer.on('asynchronous-reply', function(event, arg) {
console.log(arg); // prints "pong"
});
ipcRenderer.send('asynchronous-message', 'ping');
同樣也可以從主程式向渲染程式傳送訊息,使用的是 webContents.send方法,下面是具體的例子:
// 主程式.main.js
var window = null;
app.on('ready', function() {
window = new BrowserWindow({width: 800, height: 600});
window.loadURL('file://' + __dirname + '/index.html');
window.webContents.on('did-finish-load', function() {
window.webContents.send('ping', 'whoooooooh!');
});
});
<!-- index.html -->
<html>
<body>
<script>
require('electron').ipcRenderer.on('ping', function(event, message) {
console.log(message); // Prints "whoooooooh!"
});
</script>
</body>
</html>
2.2 remote模組
remote模組支援RPC風格的通訊,在渲染程式中獲取主程式建立的一些全域性物件和應用資訊,還可以呼叫主程式所提供的一些方法,如重啟應用、操作渲染程式等。
remote 模組提供了一種在渲染程式( 網頁) 和主程式之間進行程式間通訊( IPC) 的簡便途徑。使用remote 模組,可以呼叫主程式物件的方法,而無需顯式地傳送程式間訊息,這類似於 Java
的 RMI。
下面是從渲染程式建立一個瀏覽器視窗的例子:
const remote = require('electron').remote;
const BrowserWindow = remote.BrowserWindow;
var win = new BrowserWindow({ width: 800, height: 600 });
win.loadURL('https://github.com');
注意: 反向操作( 從主程式訪問渲染程式) ,可以使用webContents.executeJavascript.
遠端物件
remote 模組返回的每個物件( 包括函式) 都代表了主程式中的一個物件(我們稱之為遠端物件或者遠端函式)。當呼叫遠端物件的方法、執行遠端函式或者使用遠端構造器( 函式) 建立新物件時,其實就是在傳送同步的程式間訊息。
在上面的例子中, BrowserWindow 和 win 都是遠端物件,然而 new BrowserWindow 並沒有在渲染程式中建立 BrowserWindow 物件。 而是在主程式中建立了BrowserWindow 物件,並在渲染程式中返回了對應的遠端物件,即 win 物件。
請注意只有可列舉屬性才能通過 remote 進行訪問.
遠端物件的生命週期
Electron 確保在渲染程式中的遠端物件存在(換句話說,沒有被垃圾收集),那主程式中的對應物件也不會被釋放。當遠端物件被垃圾收集之後,主程式中的對應物件才會被取消關聯。如果遠端物件在渲染程式洩露了(即,存在某個表中但永遠不會釋放),那麼主程式中的對應物件也一樣會洩露,所以你必須小心不要洩露了遠端物件。
不過,主要的值型別如字串和數字,是傳遞的副本。
給主程式傳遞迴調函式
在主程式中的程式碼可以從渲染程式——remote模組——中接受回撥函式,但是使用這個功能的時候必須非常非常小心。
首先,為了避免死鎖,傳遞給主程式的回撥函式會進行非同步呼叫。所以不能期望主程式來獲得傳遞過去的回撥函式的返回值。
比如,你不能主程式中給 Array.map 傳遞來自渲染程式的函式。
// 主程式 mapNumbers.js
exports.withRendererCallback = function(mapper) {
return [1,2,3].map(mapper);
}
exports.withLocalCallback = function() {
return exports.mapNumbers(function(x) {
return x + 1;
});
}
// 渲染程式
var mapNumbers = require("remote").require("./mapNumbers");
var withRendererCb = mapNumbers.withRendererCallback(function(x) {
return x + 1;
})
var withLocalCb = mapNumbers.withLocalCallback()
console.log(withRendererCb, withLocalCb) // [true, true, true], [2, 3, 4]
如你所見,渲染器回撥函式的同步返回值沒有按預期產生,與主程式中的一模一樣的回撥函
數的返回值不同。
其次,傳遞給主程式的函式會持續到主程式對他們進行垃圾回收。
例如,下面的程式碼第一眼看上去毫無問題。給遠端物件的 close 事件繫結了一個回撥函式:
remote.getCurrentWindow().on('close', function() {
// blabla...
});
但記住主程式會一直保持對這個回撥函式的引用,除非明確的解除安裝它。如果不解除安裝,每次重新載入視窗都會再次繫結,這樣每次重啟就會洩露一個回撥函式。
更嚴重的是,由於前面安裝了回撥函式的上下文已經被釋放,所以當主程式的 close 事件觸
發的時候,會丟擲異常。
為了避免這個問題,要確保對傳遞給主程式的渲染器的回撥函式進行清理。可以清理事件處
理器,或者明確告訴主進行取消來自已經退出的渲染器程式中的回撥函式。
訪問主程式中的內建模組
在主程式中的內建模組已經被新增為 remote 模組中的屬性,所以可以直接像使
用 electron 模組一樣直接使用它們。
const app = remote.app;
方法
remote 模組有以下方法:
- remote.require(module)
module String
返回在主程式中執行 require(module) 所返回的物件。 - remote.getCurrentWindow()
返回該網頁所屬的 BrowserWindow 物件。 - remote.getCurrentWebContents()
返回該網頁的 WebContents 物件 - remote.getGlobal(name)
name String
返回在主程式中名為 name 的全域性變數(即 global[name] ) 。 - remote.process
返回主程式中的 process 物件。等同於 remote.getGlobal('process') 但是有快取
相關文章
- Electron 入門指北(二)
- 使用 TypeScript 開發 electron入門體驗TypeScript
- Electron-vue開發實戰0——Electron-vue入門Vue
- Electron實戰之程式間通訊
- electron-egg: 當代桌面開發框架,輕鬆入門electron框架
- Electron入門教程
- Electron入門指北
- (二) electron 開發環境配置開發環境
- openresty前端開發入門二REST前端
- Electron 入門指北(一)
- Electron 入門指北(三)
- electron-ipc通訊效能分析
- java webservice開發入門之二JavaWeb
- Unity3D開發入門教程(二)—— Lua入門Unity3D
- 快速入門android AIDL(開啟多程式並進行通訊)AndroidAI
- RabbitMQ 入門(一)同步通訊和非同步通訊MQ非同步
- Kotlin程式開發入門Kotlin
- 分散式入門(一)- 通訊原語和通訊庫分散式
- Android 即時通訊開發小結(二)Android
- 微信小程式初體驗,入門練手專案--通訊錄,部署上線(二)微信小程式
- spring boot + vue + element-ui全棧開發入門——基於Electron桌面應用開發Spring BootVueUI全棧
- 小程式從入門到開發
- Flutter入門教程(二)開發環境搭建Flutter開發環境
- Electron入門Demo之桌面應用計算器筆記(二)筆記
- Winsock的事件I/O非同步模型(開發網路通訊程式入門的繼續) (轉)事件非同步模型
- Electron小白入門自學筆記(一)筆記
- 12個例子帶你入門Electron
- Java開發學習(二)----IOC、DI入門案例Java
- 【Android開發入門教程】二.Android應用程式結構分析Android
- web前端技術分享Electron之IPC 通訊Web前端
- web前端培訓分享Electron之IPC 通訊Web前端
- Android技術分享| 視訊通話開發流程(二)Android
- Android入門教程 | Fragment (載入方法與通訊)AndroidFragment
- Linux程式間的通訊方式有哪些?Linux入門教程Linux
- Docker從入門到精通(六)——容器通訊Docker
- vue3 快速入門系列 —— 元件通訊Vue元件
- 基於Openfire Smack開發即時通訊應用、Spark安裝,註冊,登入,退出登入(二)MacSpark
- CAD二次開發入門:WPF類庫