remote
在渲染进程中使用主进程模块。
进程: 渲染进程
remote
模块为渲染进程(web页面)和主进程通信(IPC)提供了一种简单方法。
在Electron中, GUI 相关的模块 (如 dialog
、menu
等) 仅在主进程中可用, 在渲染进程中不可用。 为了在渲染进程中使用它们, ipc
模块是向主进程发送进程间消息所必需的。 使用 remote
模块, 你可以调用 main 进程对象的方法, 而不必显式发送进程间消息, 类似于 Java 的 RMI 。例如:从渲染进程创建浏览器窗口
const { BrowserWindow } = require('electron').remote
let win = new BrowserWindow({ width: 800, height: 600 })
win.loadURL('https://github.com')
Note: For the reverse (access the renderer process from the main process), you can use webContents.executeJavaScript.
Note: The remote module can be disabled for security reasons in the following contexts:
BrowserWindow
- by setting theenableRemoteModule
option tofalse
.<webview>
- by setting theenableremotemodule
attribute tofalse
.
远程对象(Remote Objects)
remote
模块返回的每个对象 (包括函数) 表示主进程中的一个对象 (我们称它为远程对象或远程函数)。 当调用远程对象的方法时, 调用远程函数, 或者使用远程构造函数 (函数) 创建新对象时, 实际上是在发送同步进程消息。
在上面的示例中, BrowserWindow 和
win 都是远程对象, new BrowserWindow
在渲染过程中没有创建 BrowserWindow
对象。 取而代之的是,它在主进程中创建了一个 BrowserWindow
对象,并且在渲染进程中返回相应的远程对象,即` win </ 0>对象。
注意: 当远程对象被第一次引用时,只有可枚举的属性可以通过远程访问。
注意: 当通过 remote `模块访问时,数组和缓冲区在IPC上复制。 在渲染进程中修改它们不会在主进程中修改它们,反之亦然。
远程对象的生命周期
Electron 确保只要渲染进程中的远程对象存在(换句话说,没有被垃圾收集),主进程中的相应对象将不会被释放。 当远程对象被垃圾回收后,主进程中的相应对象将被解除引用。
如果远程对象在渲染进程中泄露(例如存储在映射中,但从未释放),则主进程中的相应对象也将被泄漏,所以您应该非常小心,不要泄漏远程对象。
但是,字符串和数字等主要值的类型是通过复制发送的。
将回调传递给主进程
主进程中的代码可以接受来自渲染进程的回调 - 例如remote
模块 - 但使用此功能时应该非常小心。
首先,为了避免死锁,传递给主进程的回调被异步调用。 您不应该期望主进程获得传递回调的返回值。
例如,您不能在主进程中调用的Array.map
中使用来自渲染器进程的函数:
// 主进程 mapNumbers.js
exports.withRendererCallback = (mapper) => {
return [1, 2, 3].map(mapper)
}
exports.withLocalCallback = () => {
return [1, 2, 3].map(x => x + 1)
}
// 渲染进程
const mapNumbers = require('electron').remote.require('./mapNumbers')
const withRendererCb = mapNumbers.withRendererCallback(x => x + 1)
const withLocalCb = mapNumbers.withLocalCallback()
console.log(withRendererCb, withLocalCb)
// [undefined, undefined, undefined], [2, 3, 4]
如您所见,渲染器回调的同步返回值不是预期的,而且在主进程中也与相同回调的返回值不符。
其次,传递给主进程的回调将持续到主进程垃圾回收。
例如,下面的代码乍一看似乎是无辜的。 它为远程对象上的close
事件安装一个回调:
require('electron').remote.getCurrentWindow().on('close', () => {
// window was closed...
})
但请记住, 回调是由主进程引用的, 直到你显式卸载它。 如果不这样做, 每次重新加载窗口时这个回调将再次被安装, 每次重启时都会泄漏一个回调。
更糟的是, 由于以前安装的回调的上下文已释放, 因此在发出 close
事件时, 将在主进程中引发异常。
为了避免这个问题,请确保清除对传递给主进程的渲染器回调的引用。 这涉及到清理事件处理程序, 或者确保主进程被明确告知取消引用来自正在退出的渲染程序的回调。
访问主进程中的内置模块
主过程中的内置模块被添加为 remote
模块中的获取器,因此可以像 electron
模块一样直接使用它们。
const app = require('electron').remote.app
console.log(app)
方法
remote
模块具有以下方法:
remote.require(module)
module
String
返回any
- 主进程中require(module)
返回的对象。 由其相对路径指定的模块将相对于主进程的入口点来解析。
例如:
project/
├── main
│ ├── foo.js
│ └── index.js
├── package.json
└── renderer
└── index.js
// main process: main/index.js
const { app } = require('electron')
app.on('ready', () => { /* ... */ })
// some relative module: main/foo.js
module.exports = 'bar'
// renderer process: renderer/index.js
const foo = require('electron').remote.require('./foo') // bar
remote.getCurrentWindow()
返回 BrowserWindow
- 此网页所属的窗口
Note: Do not use removeAllListeners
on BrowserWindow
. Use of this can remove all blur
listeners, disable click events on touch bar buttons, and other unintended consequences.
remote.getCurrentWebContents()
返回 WebContents
- 此网页的 web 内容
remote.getGlobal(name)
name
String
返回any
-主进程中name
(例如global[name]
) 的全局变量。
属性
remote.process
主进程中的 process
对象。这与 remote.getGlobal('process')
相同, 但已被缓存。