Electron remote 模塊

2019-08-14 19:21 更新

remote 模塊提供了一種在渲染進(jìn)程(網(wǎng)頁(yè))和主進(jìn)程之間進(jìn)行進(jìn)程間通訊(IPC)的簡(jiǎn)便途徑。

Electron中, 與GUI相關(guān)的模塊(如 dialog, menu 等)只存在于主進(jìn)程,而不在渲染進(jìn)程中 。為了能從渲染進(jìn)程中使用它們,需要用ipc模塊來(lái)給主進(jìn)程發(fā)送進(jìn)程間消息。使用 remote 模塊,可以調(diào)用主進(jìn)程對(duì)象的方法,而無(wú)需顯式地發(fā)送進(jìn)程間消息,這類似于 Java 的 RMI。 下面是從渲染進(jìn)程創(chuàng)建一個(gè)瀏覽器窗口的例子:

const remote = require('electron').remote;
const BrowserWindow = remote.BrowserWindow;

var win = new BrowserWindow({ width: 800, height: 600 });
win.loadURL('https://github.com');

注意: 反向操作(從主進(jìn)程訪問(wèn)渲染進(jìn)程),可以使用webContents.executeJavascript.

遠(yuǎn)程對(duì)象

remote模塊返回的每個(gè)對(duì)象(包括函數(shù))都代表了主進(jìn)程中的一個(gè)對(duì)象(我們稱之為遠(yuǎn)程對(duì)象或者遠(yuǎn)程函數(shù))。 當(dāng)調(diào)用遠(yuǎn)程對(duì)象的方法、執(zhí)行遠(yuǎn)程函數(shù)或者使用遠(yuǎn)程構(gòu)造器(函數(shù))創(chuàng)建新對(duì)象時(shí),其實(shí)就是在發(fā)送同步的進(jìn)程間消息。

在上面的例子中, BrowserWindow 和 win 都是遠(yuǎn)程對(duì)象,然而 new BrowserWindow 并沒(méi)有在渲染進(jìn)程中創(chuàng)建 BrowserWindow 對(duì)象。 而是在主進(jìn)程中創(chuàng)建了 BrowserWindow 對(duì)象,并在渲染進(jìn)程中返回了對(duì)應(yīng)的遠(yuǎn)程對(duì)象,即 win 對(duì)象。

請(qǐng)注意只有 可枚舉屬性 才能通過(guò) remote 進(jìn)行訪問(wèn).

遠(yuǎn)程對(duì)象的生命周期

Electron 確保在渲染進(jìn)程中的遠(yuǎn)程對(duì)象存在(換句話說(shuō),沒(méi)有被垃圾收集),那主進(jìn)程中的對(duì)應(yīng)對(duì)象也不會(huì)被釋放。 當(dāng)遠(yuǎn)程對(duì)象被垃圾收集之后,主進(jìn)程中的對(duì)應(yīng)對(duì)象才會(huì)被取消關(guān)聯(lián)。

如果遠(yuǎn)程對(duì)象在渲染進(jìn)程泄露了(即,存在某個(gè)表中但永遠(yuǎn)不會(huì)釋放),那么主進(jìn)程中的對(duì)應(yīng)對(duì)象也一樣會(huì)泄露, 所以你必須小心不要泄露了遠(yuǎn)程對(duì)象。If the remote object is leaked in the renderer process (e.g. stored in a map but never freed), the corresponding object in the main process will also be leaked, so you should be very careful not to leak remote objects.

不過(guò),主要的值類型如字符串和數(shù)字,是傳遞的副本。

給主進(jìn)程傳遞回調(diào)函數(shù)

在主進(jìn)程中的代碼可以從渲染進(jìn)程——remote模塊——中接受回調(diào)函數(shù),但是使用這個(gè)功能的時(shí)候必須非常非常小心。Code in the main process can accept callbacks from the renderer - for instance the remotemodule - but you should be extremely careful when using this feature.

首先,為了避免死鎖,傳遞給主進(jìn)程的回調(diào)函數(shù)會(huì)進(jìn)行異步調(diào)用。所以不能期望主進(jìn)程來(lái)獲得傳遞過(guò)去的回調(diào)函數(shù)的返回值。First, in order to avoid deadlocks, the callbacks passed to the main process are called asynchronously. You should not expect the main process to get the return value of the passed callbacks.

比如,你不能主進(jìn)程中給Array.map傳遞來(lái)自渲染進(jìn)程的函數(shù)。

// 主進(jìn)程 mapNumbers.js
exports.withRendererCallback = function(mapper) {
  return [1,2,3].map(mapper);
}

exports.withLocalCallback = function() {
  return exports.mapNumbers(function(x) {
    return x + 1;
  });
}
// 渲染進(jìn)程
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]

如你所見(jiàn),渲染器回調(diào)函數(shù)的同步返回值沒(méi)有按預(yù)期產(chǎn)生,與主進(jìn)程中的一模一樣的回調(diào)函數(shù)的返回值不同。

其次,傳遞給主進(jìn)程的函數(shù)會(huì)持續(xù)到主進(jìn)程對(duì)他們進(jìn)行垃圾回收。

例如,下面的代碼第一眼看上去毫無(wú)問(wèn)題。給遠(yuǎn)程對(duì)象的close事件綁定了一個(gè)回調(diào)函數(shù):

remote.getCurrentWindow().on('close', function() {
  // blabla...
});

但記住主進(jìn)程會(huì)一直保持對(duì)這個(gè)回調(diào)函數(shù)的引用,除非明確的卸載它。如果不卸載,每次重新載入窗口都會(huì)再次綁定,這樣每次重啟就會(huì)泄露一個(gè)回調(diào)函數(shù)。

更嚴(yán)重的是,由于前面安裝了回調(diào)函數(shù)的上下文已經(jīng)被釋放,所以當(dāng)主進(jìn)程的 close 事件觸發(fā)的時(shí)候,會(huì)拋出異常。

為了避免這個(gè)問(wèn)題,要確保對(duì)傳遞給主進(jìn)程的渲染器的回調(diào)函數(shù)進(jìn)行清理??梢郧謇硎录幚砥鳎蛘呙鞔_告訴主進(jìn)行取消來(lái)自已經(jīng)退出的渲染器進(jìn)程中的回調(diào)函數(shù)。

訪問(wèn)主進(jìn)程中的內(nèi)置模塊

在主進(jìn)程中的內(nèi)置模塊已經(jīng)被添加為remote模塊中的屬性,所以可以直接像使用electron模塊一樣直接使用它們。

const app = remote.app;

方法

remote 模塊有以下方法:

remote.require(module)

  • module String

返回在主進(jìn)程中執(zhí)行 require(module) 所返回的對(duì)象。

remote.getCurrentWindow()

返回該網(wǎng)頁(yè)所屬的 BrowserWindow 對(duì)象。

remote.getCurrentWebContents()

返回該網(wǎng)頁(yè)的 WebContents 對(duì)象

remote.getGlobal(name)

  • name String

返回在主進(jìn)程中名為 name 的全局變量(即 global[name]) 。

remote.process

返回主進(jìn)程中的 process 對(duì)象。等同于 remote.getGlobal('process') 但是有緩存。

以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)