当前位置: 首页 > 文档资料 > Electron 中文文档 >

remote

优质
小牛编辑
158浏览
2023-12-01

在渲染进程中使用主进程模块。

进程: 渲染进程

remote 模块为渲染进程(web页面)和主进程通信(IPC)提供了一种简单方法。

在Electron中, GUI 相关的模块 (如 dialogmenu 等) 仅在主进程中可用, 在渲染进程中不可用。 为了在渲染进程中使用它们, ipc 模块是向主进程发送进程间消息所必需的。 使用 remote 模块, 你可以调用 main 进程对象的方法, 而不必显式发送进程间消息, 类似于 Java 的 RMI 。
例如:从渲染进程创建浏览器窗口

const { BrowserWindow } = require('electron').remote
let win = new BrowserWindow({ width: 800, height: 600 })
win.loadURL('https://github.com')

注意: 反过来(如果需要从主进程访问渲染进程),可以使用 webContents. executeJavascript 。

注意事项: 因为安全原因,remote 模块能在以下几种情况下被禁用:

  • BrowserWindow - 通过设置 enableRemoteModule 选项为 false
  • <webview> - 通过把 enableremotemodule属性设置成 false

Use main process modules from the renderer process.

Process: Renderer

The remote module provides a simple way to do inter-process communication (IPC) between the renderer process (web page) and the main process.

In Electron, GUI-related modules (such as dialog, menu etc.) are only available in the main process, not in the renderer process. In order to use them from the renderer process, the ipc module is necessary to send inter-process messages to the main process. With the remote module, you can invoke methods of the main process object without explicitly sending inter-process messages, similar to Java's RMI. An example of creating a browser window from a renderer process:

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 the enableRemoteModule option to false.
  • <webview> - by setting the enableremotemodule attribute to false.

远程对象(Remote Objects)

remote 模块返回的每个对象 (包括函数) 表示主进程中的一个对象 (我们称它为远程对象或远程函数)。 当调用远程对象的方法时, 调用远程函数, 或者使用远程构造函数 (函数) 创建新对象时, 实际上是在发送同步进程消息。

在上面的示例中, [ BrowserWindow win ](browser-window. md) 都是远程对象, new BrowserWindow 在渲染过程中没有创建 BrowserWindow 对象。 取而代之的是,它在主进程中创建了一个 BrowserWindow对象,并且在渲染进程中返回相应的远程对象,即` win </ 0>对象。

注意: 当远程对象被第一次引用时,只有可枚举的属性可以通过远程访问。

注意: 当通过remote `模块访问时,数组和缓冲区在IPC上复制。 在渲染进程中修改它们不会在主进程中修改它们,反之亦然。

Remote Objects

Each object (including functions) returned by the remote module represents an object in the main process (we call it a remote object or remote function). When you invoke methods of a remote object, call a remote function, or create a new object with the remote constructor (function), you are actually sending synchronous inter-process messages.

In the example above, both BrowserWindow and win were remote objects and new BrowserWindow didn't create a BrowserWindow object in the renderer process. Instead, it created a BrowserWindow object in the main process and returned the corresponding remote object in the renderer process, namely the win object.

Note: Only enumerable properties which are present when the remote object is first referenced are accessible via remote.

Note: Arrays and Buffers are copied over IPC when accessed via the remote module. Modifying them in the renderer process does not modify them in the main process and vice versa.

远程对象的生命周期

Electron 确保只要渲染进程中的远程对象一直存在(换句话说,没有被回收),主进程中的相应对象就不会被释放。 当远程对象被垃圾回收后,主进程中的相应对象将被解除引用。

如果远程对象在渲染进程中泄露(例如存储在映射中,但从未释放),则主进程中的相应对象也将被泄漏,所以您应该非常小心,不要泄漏远程对象。

但是,字符串和数字等主要值的类型是通过复制发送的。

Lifetime of Remote Objects

Electron makes sure that as long as the remote object in the renderer process lives (in other words, has not been garbage collected), the corresponding object in the main process will not be released. When the remote object has been garbage collected, the corresponding object in the main process will be dereferenced.

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.

Primary value types like strings and numbers, however, are sent by copy.

将回调传递给主进程

主进程中的代码可以接受来自渲染进程的回调 - 例如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 事件时, 将在主进程中引发异常。

为了避免这个问题,请确保清除对传递给主进程的渲染器回调的引用。 这涉及到清理事件处理程序, 或者确保主进程被明确告知取消引用来自正在退出的渲染程序的回调。

Passing callbacks to the main process

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.

For instance you can't use a function from the renderer process in an Array.map called in the main process:

// main process mapNumbers.js
exports.withRendererCallback = (mapper) => {
  return [1, 2, 3].map(mapper)
}
exports.withLocalCallback = () => {
  return [1, 2, 3].map(x => x + 1)
}
// renderer process
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]

As you can see, the renderer callback's synchronous return value was not as expected, and didn't match the return value of an identical callback that lives in the main process.

Second, the callbacks passed to the main process will persist until the main process garbage-collects them.

For example, the following code seems innocent at first glance. It installs a callback for the close event on a remote object:

require('electron').remote.getCurrentWindow().on('close', () => {
  // window was closed...
})

But remember the callback is referenced by the main process until you explicitly uninstall it. If you do not, each time you reload your window the callback will be installed again, leaking one callback for each restart.

To make things worse, since the context of previously installed callbacks has been released, exceptions will be raised in the main process when the close event is emitted.

To avoid this problem, ensure you clean up any references to renderer callbacks passed to the main process. This involves cleaning up event handlers, or ensuring the main process is explicitly told to dereference callbacks that came from a renderer process that is exiting.

访问主进程中的内置模块

主过程中的内置模块被添加为 remote 模块中的获取器,因此可以像 electron 模块一样直接使用它们。

const app = require('electron').remote.app
console.log(app)

Accessing built-in modules in the main process

The built-in modules in the main process are added as getters in the remote module, so you can use them directly like the electron module.

const app = require('electron').remote.app
console.log(app)

方法

remote 模块具有以下方法:

Methods

The remote module has the following methods:

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.require(module)

  • module String

Returns any - The object returned by require(module) in the main process. Modules specified by their relative path will resolve relative to the entrypoint of the main process.

e.g.

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 - 此网页所属的窗口

注意事项: 请勿在BrowserWindow上使用 removeAllListeners。 使用这个可导致移除 blur 监听,禁用点击触控按钮的事件,或者其它意外的后果。

remote.getCurrentWindow()

Returns BrowserWindow - The window to which this web page belongs.

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.getCurrentWebContents()

Returns WebContents - The web contents of this web page.

remote.getGlobal(name)

  • name String

返回 any-主进程中 name (例如 global[name]) 的全局变量。

remote.getGlobal(name)

  • name String

Returns any - The global variable of name (e.g. global[name]) in the main process.

属性

Properties

remote.process

主进程中的 process 对象。这与 remote.getGlobal('process') 相同, 但已被缓存。

remote.process

The process object in the main process. This is the same as remote.getGlobal('process') but is cached.