您现在的位置是:亿华云 > 人工智能

Electron 进程间通信的四种方式

亿华云2025-10-03 06:44:06【人工智能】0人已围观

简介在electron中进行使用 ipcMain 和 ipcRenderer 模块,通过开发人员定义的“通道”传递消息来进行通信。新的版本中electron推荐使用上下文隔离渲染器进程进行通信,这种方式的

在electron中进行使用 ipcMain 和 ipcRenderer 模块,进程间通通过开发人员定义的种方“通道”传递消息来进行通信。新的进程间通版本中electron推荐使用上下文隔离渲染器进程进行通信,这种方式的种方好处是无需在渲染进程中直接使用ipcRenderer发送消息,这种在渲染进程中调用nodejs对象的进程间通方法对于渲染进程有侵入性。当我们使用vue或者其他前端框架开发界面时,种方上下文隔离方式使用起来更加方便,进程间通基本上感受不到electron对前端框架的种方影响。

上下文隔离的进程间通进程间通信方式有四种:

1、渲染器进程到主进程(单向)

要将单向 IPC 消息从渲染器进程发送到主进程,种方您可以使用 ipcRenderer.send API 发送消息,进程间通然后使用 ipcMain.on API 接收。种方通常使用场景是进程间通从 Web 向主进程发送消息。

使用 ipcMain.on 监听事件

在主进程中,种方使用 ipcMain.on 在 set-title 通道上设置一个 IPC 监听器:

const handleSetTitle = (event,进程间通 title) => {

const webContents = event.sender

const win = BrowserWindow.fromWebContents(webContents)

win.setTitle(title)

}

ipcMain.on(set-title, handleSetTitle)

上面的 handleSetTitle 回调函数有两个参数:一个 IpcMainEvent 结构和一个 title 字符串。 每当消息通过 set-title 通道传入时,此函数找到附加到消息发送方的 BrowserWindow 实例,并在该实例上调用win.setTitle函数设置窗口标题。

通过预加载脚本暴露 ipcRenderer.send

要将消息发送到上面创建的监听器,您可以使用 ipcRenderer.send。默认情况下,渲染器进程没有权限访问 Node.js 和 Electron 模块。 作为应用开发者,云南idc服务商你需要使用 contextBridge 来选择要从预加载脚本中暴露哪些 API。

在您的预加载脚本中添加以下代码,向渲染器进程暴露一个全局的 window.electronAPI 变量。

import { contextBridge, ipcRenderer } from electron

contextBridge.exposeInMainWorld(electronAPI, {

setTitle: (title) => ipcRenderer.send(set-title, title)

})

然后我们就能够在渲染器进程中使用

window.electronAPI.setTitle() 函数。

构建渲染器进程 UI

在 BrowserWindow 加载的我们的 HTML 文件中,添加一个由文本输入框和按钮组成的基本用户界面:

Hello World!

Title:

</html>

为了使这些元素具有交互性,我们将在导入的 renderer.js 文件中添加几行代码,以利用从预加载脚本中暴露的 window.electronAPI 功能:

const setButton = document.getElementById(btn)

const titleInput = document.getElementById(title)

setButton.addEventListener(click, () => {

const title = titleInput.value

window.electronAPI.setTitle(title)

});

这种方式只能把消息从web中发送到主进程,并不能从主进程中获取到返回值。

2、渲染器进程到主进程(双向)

双向 IPC 的一个常见应用是从渲染器进程代码调用主进程模块并等待结果。 这可以通过将 ipcRenderer.invoke 与 ipcMain.handle 搭配使用来完成。

我们依然通过一个示例来了解这种通信方式:

使用 ipcMain.handle 监听事件

在主进程中,我们将创建一个 handleFileOpen() 函数,它调用 dialog.showOpenDialog 并返回用户选择的文件路径值。 每当渲染器进程通过 dialog:openFile 通道发送 ipcRender.invoke 消息时,此函数被用作一个回调。 然后,返回值将作为一个 Promise 返回到最初的 invoke 调用。

async function handleFileOpen() {

const { canceled, filePaths } = await dialog.showOpenDialog()

if (canceled) {

return

} else {

return filePaths[0] // 返回文件名给渲染进程

}

}

ipcMain.handle(dialog:openFile, handleFileOpen)通过预加载脚本暴露 ipcRenderer.invoke

在预加载脚本中,我们暴露了一个单行的 openFile 函数,亿华云计算它调用并返回 ipcRenderer.invoke(dialog:openFile) 的值。

import { contextBridge, ipcRenderer } from electron

contextBridge.exposeInMainWorld(electronAPI, {

openFile: () => ipcRenderer.invoke(dialog:openFile)

})构建渲染器进程 UI

在渲染器中调用。

window.electronAPI.openFile调用打开文件对话框,并获取打开的文件名,并显示在界面上。

Dialog

File path:

</html>

渲染器进程脚本。

const btn = document.getElementById(btn)

const filePathElement = document.getElementById(filePath)

btn.addEventListener(click, async () => {

const filePath = await window.electronAPI.openFile()

filePathElement.innerText = filePath

})

3、主进程到渲染器进程(双向)

将消息从主进程发送到渲染器进程时,需要指定是哪一个渲染器接收消息。 消息需要通过其 WebContents 实例发送到渲染器进程。 此 WebContents 实例包含一个 send 方法,其使用方式与 ipcRenderer.send 相同。

使用 webContents 模块发送消息

在菜单中通过使用 webContents.send 将 IPC 消息从主进程发送到目标渲染器。

const menu = Menu.buildFromTemplate([

{

label: app.name,

submenu: [

{

click: () => mainWindow.webContents.send(update-counter, 1),

label: Increment,

},

{

click: () => mainWindow.webContents.send(update-counter, -1),

label: Decrement,

}

]

}

])

Menu.setApplicationMenu(menu)通过预加载脚本暴露 ipcRenderer.on

使用预加载脚本中的 contextBridge 和 ipcRenderer 模块向渲染器进程发送消息:

import { contextBridge, ipcRenderer } from electron

contextBridge.exposeInMainWorld(electronAPI, {

onUpdateCounter: (callback) => ipcRenderer.on(update-counter, callback)

})

加载预加载脚本后,渲染器进程应有权访问。

window.electronAPI.onUpdateCounter() 监听器函数。

构建渲染器进程 UI

Menu Counter

Current value: 0

</html>

更新 HTML 文档中的值。

const counter = document.getElementById(counter)

window.electronAPI.onUpdateCounter((_event, value) => {

const oldValue = Number(counter.innerText)

const newValue = oldValue + value

counter.innerText = newValue

})返回一个回复

对于从主进程到渲染器进程的 IPC,没有与 ipcRenderer.invoke 等效的 API。 不过,您可以从 ipcRenderer.on 回调中将回复发送回主进程。

在渲染器进程中,使用 event 参数,通过 counter-value 通道将回复发送回主进程。

const counter = document.getElementById(counter)

window.electronAPI.onUpdateCounter((event, value) => {

const oldValue = Number(counter.innerText)

const newValue = oldValue + value

counter.innerText = newValue

event.sender.send(counter-value, newValue) // 发送消息到主进程

})

在主进程中,监听 counter-value 事件并适当地处理它们。香港云服务器

//...

ipcMain.on(counter-value, (_event, value) => {

console.log(value) // 将打印到 Node 控制台

})

//...

4、渲染器进程到渲染器进程

没有直接的方法可以使用 ipcMain 和 ipcRenderer 模块在 Electron 中的渲染器进程之间发送消息。 为此,我们有两种选择:

将主进程作为渲染器之间的消息代理。 这需要将消息从一个渲染器发送到主进程,然后主进程将消息转发到另一个渲染器。从主进程将一个 MessagePort 传递到两个渲染器。 这将允许在初始设置后渲染器之间直接进行通信。Electron与Vue进程通信

上面我们介绍了Electron的四种进程间通信方式,那么将Electron和Vue结合起来,其本质依然是主进程与渲染进程之间的通信,通信方式不会由什么变化,只是目前比较流行的TS编程方式会让一些人束手无策,会报一些属性不存在的错误,这就需要我们去为TS声明这些额外的属性。例如:

(1)注册上下文隔离接口。

在预加载脚本中添加如下代码:

import os from os;

import { contextBridge } from electron;

contextBridge.exposeInMainWorld(electronAPI, {

platform: os.platform(),

});

(2)为TS声明类型。

// src/types/global.d.ts

export interface IElectronAPI {

platform: string;

}

declare global {

interface Window {

electronAPI: IElectronAPI;

}

}

(3)在Vue中调用接口.

// src/App.vue

// This starter template is using Vue 3

// Check out https://vuejs.org/api/sfc-script-setup.html#script-setup

import HelloWorld from ./components/HelloWorld.vue;

const platform = window.electronAPI.platform;

Vue logo

</template>

很赞哦!(88)