# remote
`remote` 模塊提供了一種在渲染進程(網頁)和主進程之間進行進程間通訊(IPC)的簡便途徑。
Electron中, 與GUI相關的模塊(如 `dialog`, `menu` 等)只存在于主進程,而不在渲染進程中
。為了能從渲染進程中使用它們,需要用`ipc`模塊來給主進程發送進程間消息。使用 `remote`
模塊,可以調用主進程對象的方法,而無需顯式地發送進程間消息,這類似于 Java 的 [RMI][rmi]。
下面是從渲染進程創建一個瀏覽器窗口的例子:
```javascript
const remote = require('electron').remote;
const BrowserWindow = remote.BrowserWindow;
var win = new BrowserWindow({ width: 800, height: 600 });
win.loadURL('https://github.com');
```
**注意:** 反向操作(從主進程訪問渲染進程),可以使用[webContents.executeJavascript](web-contents.md#webcontentsexecutejavascriptcode-usergesture).
## 遠程對象
`remote`模塊返回的每個對象(包括函數)都代表了主進程中的一個對象(我們稱之為遠程對象或者遠程函數)。
當調用遠程對象的方法、執行遠程函數或者使用遠程構造器(函數)創建新對象時,其實就是在發送同步的進程間消息。
在上面的例子中, `BrowserWindow` 和 `win` 都是遠程對象,然而
`new BrowserWindow` 并沒有在渲染進程中創建 `BrowserWindow` 對象。
而是在主進程中創建了 `BrowserWindow` 對象,并在渲染進程中返回了對應的遠程對象,即
`win` 對象。
請注意只有 [可枚舉屬性](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Enumerability_and_ownership_of_properties) 才能通過 remote 進行訪問.
## 遠程對象的生命周期
Electron 確保在渲染進程中的遠程對象存在(換句話說,沒有被垃圾收集),那主進程中的對應對象也不會被釋放。
當遠程對象被垃圾收集之后,主進程中的對應對象才會被取消關聯。
如果遠程對象在渲染進程泄露了(即,存在某個表中但永遠不會釋放),那么主進程中的對應對象也一樣會泄露,
所以你必須小心不要泄露了遠程對象。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.
不過,主要的值類型如字符串和數字,是傳遞的副本。
## 給主進程傳遞回調函數
在主進程中的代碼可以從渲染進程——`remote`模塊——中接受回調函數,但是使用這個功能的時候必須非常非常小心。Code in the main process can accept callbacks from the renderer - for instance
the `remote` module - but you should be extremely careful when using this
feature.
首先,為了避免死鎖,傳遞給主進程的回調函數會進行異步調用。所以不能期望主進程來獲得傳遞過去的回調函數的返回值。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.
比如,你不能主進程中給`Array.map`傳遞來自渲染進程的函數。
```javascript
// 主進程 mapNumbers.js
exports.withRendererCallback = function(mapper) {
return [1,2,3].map(mapper);
}
exports.withLocalCallback = function() {
return exports.mapNumbers(function(x) {
return x + 1;
});
}
```
```javascript
// 渲染進程
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`事件綁定了一個回調函數:
```javascript
remote.getCurrentWindow().on('close', function() {
// blabla...
});
```
但記住主進程會一直保持對這個回調函數的引用,除非明確的卸載它。如果不卸載,每次重新載入窗口都會再次綁定,這樣每次重啟就會泄露一個回調函數。
更嚴重的是,由于前面安裝了回調函數的上下文已經被釋放,所以當主進程的 `close` 事件觸發的時候,會拋出異常。
為了避免這個問題,要確保對傳遞給主進程的渲染器的回調函數進行清理。可以清理事件處理器,或者明確告訴主進行取消來自已經退出的渲染器進程中的回調函數。
## 訪問主進程中的內置模塊
在主進程中的內置模塊已經被添加為`remote`模塊中的屬性,所以可以直接像使用`electron`模塊一樣直接使用它們。
```javascript
const app = remote.app;
```
## 方法
`remote` 模塊有以下方法:
### `remote.require(module)`
* `module` String
返回在主進程中執行 `require(module)` 所返回的對象。
### `remote.getCurrentWindow()`
返回該網頁所屬的 [`BrowserWindow`](browser-window.md) 對象。
### `remote.getCurrentWebContents()`
返回該網頁的 [`WebContents`](web-contents.md) 對象
### `remote.getGlobal(name)`
* `name` String
返回在主進程中名為 `name` 的全局變量(即 `global[name]`) 。
### `remote.process`
返回主進程中的 `process` 對象。等同于
`remote.getGlobal('process')` 但是有緩存。
[rmi]: http://en.wikipedia.org/wiki/Java_remote_method_invocation
- 介紹
- 常見問題
- Electron 常見問題
- 向導
- 支持平臺
- 分發應用
- 提交應用到 Mac App Store
- 打包應用
- 使用 Node 原生模塊
- 主進程調試
- 使用 Selenium 和 WebDriver
- 使用開發人員工具擴展
- 使用 Pepper Flash 插件
- 使用 Widevine CDM 插件
- 教程
- 快速入門
- 桌面環境集成
- 在線/離線事件探測
- API文檔
- 簡介
- 進程對象
- 支持的 Chrome 命令行開關
- 環境變量
- 自定義的 DOM 元素
- File 對象
- <webview> 標簽
- window.open 函數
- 在主進程內可用的模塊
- app
- autoUpdater
- BrowserWindow
- contentTracing
- dialog
- globalShortcut
- ipcMain
- Menu
- MenuItem
- powerMonitor
- powerSaveBlocker
- protocol
- session
- webContents
- Tray
- 在渲染進程(網頁)內可用的模塊
- desktopCapturer
- ipcRenderer
- remote
- webFrame
- 在兩種進程中都可用的模塊
- clipboard
- crashReporter
- nativeImage
- screen
- shell
- 開發
- 代碼規范
- 源碼目錄結構
- 與 NW.js(原 node-webkit)在技術上的差異
- 構建系統概覽
- 構建步驟(OS X)
- 構建步驟(Windows)
- 構建步驟(Linux)
- 在調試中使用 Symbol Server