Electron 进程通信
预加载(preload)脚本只能访问部分 Node.js API,但是主进程可以访问全部API。此时,需要使用进程通信。
比如,在preload.js中,不能访问__dirname,不能使用 Node 中的 fs 模块,但主进程(main.js )是可以的,这时候就需要使用进程通信。也就是说:要让 preload.js 通知 main.js,去调用 Node.js API 实现功能。
Electron 进程通信:
- IPC:全称是 InterProcess Communication ,即:进程间通信。
- IPC连接不同进程:在 Electron 应用中,主进程和渲染进程各自有不同的职责和运行环境。IPC是它们之间进行交互和协同工作的关键机制。没有有效的 IPC,主进程和渲染进程将无法有效地沟通和协调,导致应用功能受限。
- 调用原生 API 的唯一途径:IPC 是 Electron 中最为核心的内容。IPC 是从 UI(通常在渲染进程中)调用原生 API 的唯一方法。这意味着如果想要在 Electron 应用中实现诸如文件系统操作、与操作系统交互等功能,必须通过 IPC 让主进程执行这些操作,然后将结果返回给渲染进程进行展示或进一步处理。
- Electron 提供了
ipcMain和ipcRenderer模块用于主进程和渲染进程之间的通信。-
ipcMain(主进程中使用,从主进程到渲染进程的异步通信。):- 发送消息时,事件名称为
channel,即 通信通道。 - 回复同步信息时,需要设置
event.returnValue。 - 可以使用
event.reply(...)将异步消息发送回发送者。
- 发送消息时,事件名称为
-
ipcRenderer(渲染进程中使用,从渲染器进程到主进程的异步通信。):
-
模式1:渲染器进程到主进程(单向)
-
概述:要将单向 IPC 消息从渲染器进程发送到主进程,需要在渲染器进程中
ipcRenderer.send发送消息,在主进程中使⽤ipcMain.on接收消息。 -
常用于:从 Web 内容调用主进程 API。
-
ipcRenderer.send(channel,...args)- 用于从渲染进程向主进程发送消息。
channel:字符串,表示消息的通道名称。主进程可以通过监听这个特定的通道名称来接收来自渲染进程的消息。例如:可以定义一个名为'custom-action'的通道。...args:这是一个可变参数,可以传递任意数量的参数。这些参数可以是任何有效的 JavaScript 值,如字符串、数字、对象等。- 用于单向通信的
ipcRenderer.sendAPI 也可用于双向通信。在 Electron 7 之前,官方推荐使用ipcRenderer.send进行异步双向通信。在 Electron 7 中,官方添加ipcRenderer.invokeAPI,用于处理渲染器进程中双向 IPC。
-
ipcMain.on(channel, listener)- 在主进程中监听来自渲染进程的特定通道消息。
hannel:这是一个字符串,表示特定的通信通道名称。渲染进程使用相同的通道名称通过ipcRenderer.send或ipcRenderer.invoke向主进程发送消息。listener:这是一个回调函数,当主进程接收到来自渲染进程通过指定通道发送的消息时,这个回调函数会被执行。- 回调函数通常接受两个参数:
event和args。event代表事件对象,可用于回复渲染进程等操作;args是渲染进程发送的参数,可以是单个值或一组值,具体取决于渲染进程的发送方式。
- 回调函数通常接受两个参数:
示例:
实现需求:点击按钮后,在⽤户的 D 盘创建⼀个 hello.txt ⽂件,⽂件内容来⾃于⽤户输⼊。
- 在页面中添加相关元素
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8" /><metahttp-equiv="Content-Security-Policy"content="default-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:;"/><title>Electron</title><link rel="stylesheet" href="./index.css"></head><body><input id="content" type="text"><br><br><button id="btn">在⽤户的D盘创建⼀个hello.txt</button></body><script src="./render.js"></script>
</html>
- 在
preload.js中使⽤ipcRenderer.send('信道', 参数)发送消息,与主进程通信。
// contextBridge:在隔离的上下文中创建一个安全的、双向的、同步的桥梁。
// ipcRenderer是渲染进程中用于与主进程进行通信的模块。
const {contextBridge, ipcRenderer} = require('electron')// 把方法/数据暴露给渲染进程
contextBridge.exposeInMainWorld('customAPI', {saveFile: data => {// 渲染进程给主进程发送⼀个消息ipcRenderer.send('save-file', data)}
})
- 在
render.js中,调用preload.js暴露的saveFile方法,通知主进程
const btn = document.getElementById('btn');
const content = document.getElementById('content');
btn.addEventListener('click', () => {// 在render.js 调用 preload.js 暴露出来的saveFile方法,通知主进程customAPI.saveFile(content.value);
});
- 主进程中,在加载页面之前,使用
ipcMain.on('信道', 回调)配置对应回调函数,接收
消息。
const { app, BrowserWindow, ipcMain } = require('electron');
const path = require('path')
const fs = require('fs')
// 保存文件
function saveFile(event,data) {console.log(event, data)fs.writeFileSync('D:/hello.txt',data)// 通过 'response-save-file' 通道将结果回复给渲染进程。event.reply('response-save-file', '保存文件啦!');
}function createWindow() {const win = new BrowserWindow({width: 1000, // 窗口宽度height: 800, // 窗口高度webPreferences: {// 此处只能使用绝对路径preload: path.join(__dirname, 'preload.js')}});// 主进程注册对应回调ipcMain.on('save-file',saveFile)// 在窗口中加载一个远程页面win.loadFile('./pages/index.html');
}
渲染进程与主进程通信的流程
- 渲染进程触发:
- 当渲染进程中的某个事件发生时,比如用户点击按钮或页面加载完成,可以调用
ipcRenderer.send('信道', 参数)方法向主进程发送消息。
- 当渲染进程中的某个事件发生时,比如用户点击按钮或页面加载完成,可以调用
- 主进程接收和处理:
- 主进程使用
ipcMain.on('信道', 回调)方法监听特定的通道名称。当主进程接收到来自渲染进程的消息时,它可以根据通道名称和传递的参数执行相应的操作。
- 主进程使用
- 渲染进程接收回复:
- 渲染进程可以使用
ipcRenderer.on方法监听主进程的回复通道。当渲染进程接收到主进程的回复时,可以根据结果进行界面更新或其他处理。
- 渲染进程可以使用
模式2:渲染器进程到主进程(双向)
概述:渲染进程通过 ipcRenderer.invoke 发送消息,主进程使⽤ ipcMain.handle 接收并处理消
息。
常用于:从渲染器进程代码调用主进程模块并等待结果 。
ipcRenderer.invoke(channel, ...args)channel:这是一个字符串,表示消息的通道名称。与ipcRenderer.send类似,主进程通过监听这个特定的通道名称来接收来自渲染进程的请求。...args:这是一个可变参数,可以传递任意数量的参数给主进程。这些参数可以是任何有效的 JavaScript 值,用于向主进程提供请求所需的信息。ipcRender.invoke的返回值是 Promise 实例。
ipcMain.handle(channel, listener)channel:一个字符串,代表特定的通信通道名称。listener:一个回调函数,当主进程接收到来自渲染进程通过指定通道发送的同步请求时,这个回调函数会被执行。- 回调函数通常接受两个参数:
event和args。event代表事件对象,可用于回复渲染进程等操作;args是渲染进程发送的参数,可以是单个值或一组值,具体取决于渲染进程的发送方式。 - 回调函数需要返回一个值,这个值将作为响应发送回渲染进程。
- 回调函数通常接受两个参数:
示例:
实现需求:点击按钮从 D 盘读取 hello.txt 中的内容,并将结果呈现在页面上。
- 在页面中添加相关元素
<div id="content"></div>
<button id="btn">读取⽤户D盘的hello.txt</button
- 在
preload.js中使⽤ipcRenderer.invoke('信道', 参数)发送消息,与主进程通信。
// contextBridge:在隔离的上下文中创建一个安全的、双向的、同步的桥梁。
// ipcRenderer是渲染进程中用于与主进程进行通信的模块。
const {contextBridge, ipcRenderer} = require('electron')// 把方法/数据暴露给渲染进程
contextBridge.exposeInMainWorld('customAPI', {readFile: () => {// invoke 的返回值永远是Promisereturn ipcRenderer.invoke('read-file')}
})
- 在
render.js中,调用preload.js暴露的saveFile方法,通知主进程
const btn = document.getElementById('btn');
const content = document.getElementById('content');
btn.addEventListener('click', async () => {let txt = await customAPI.readFile();content.innerHTML = txt
});
- 主进程中,在加载页面之前,使用
ipcMain.handle('信道', 回调)配置对应回调函数,接收
消息。
const { app, BrowserWindow, ipcMain } = require('electron');
const path = require('path')
const fs = require('fs')
// 保存文件
function readFile(event,data) {return fs.readFileSync('D:/hello.txt').toString()
}function createWindow() {const win = new BrowserWindow({width: 1000, // 窗口宽度height: 800, // 窗口高度autoHideMenuBar: true, // 隐藏菜单栏webPreferences: {// 此处只能使用绝对路径preload: path.join(__dirname, 'preload.js')}});// 主进程注册对应回调ipcMain.handle('read-file', readFile)// 在窗口中加载一个远程页面win.loadFile('./pages/index.html');
}
ipcRenderer.invoke(channel, ...args) 与 ipcRenderer.send(channel, ...args) 用于双向IPC的区别
ipcRenderer.send需要设置第二个ipcRenderer.on监听器来处理渲染器进程中的响应。 使用ipcRenderer.invoke,直接获得作为 Promise 返回到原始 API 调用的响应值。- 没有显而易见的方法可以将
ipcRenderer.on('asynchronous-reply', (_event, arg) => {})消息与原始的ipcRenderer.send('asynchronous-message')消息配对。 如果不写备注,开发者可能也不知道asynchronous-reply是asynchronous-message通道的回复结果。如果通过这些通道非常频繁地来回传递消息,则需要添加其他应用代码来单独跟踪每个调用和响应。
模式3:主进程到渲染器进程
概述:主进程使用 win.webContents.send 发送消息,渲染进程使⽤ ipcRenderer.on 接收并处理消
息。
常用于:从主进程主动发送消息到渲染器进程。
示例:
需求:应⽤加载 6 秒钟后,主动给渲染进程发送⼀个消息
- 主进程中,使⽤
win.webContents.send('信道', 数据)发送消息。
const { app, BrowserWindow, ipcMain } = require('electron');
const path = require('path');
function createWindow() {const win = new BrowserWindow({width: 1000, // 窗口宽度height: 800, // 窗口高度autoHideMenuBar: true, // 隐藏菜单栏webPreferences: {// 此处只能使用绝对路径preload: path.join(__dirname, 'preload.js')}});// 在窗口中加载一个远程页面win.loadFile('./pages/index.html');// 创建⼀个定时器setTimeout(() => {win.webContents.send('message', 'hello!');}, 6000);
}
preload.js中使⽤ipcRenderer.on ('信道', 回调)接收消息,并配置回调函数。
window.onload = () => {customAPI.getMessage(logMessage);
};
function logMessage(event, str) {console.log(event, str);
}
相关文章:
Electron 进程通信
预加载(preload)脚本只能访问部分 Node.js API,但是主进程可以访问全部API。此时,需要使用进程通信。 比如,在preload.js中,不能访问__dirname,不能使用 Node 中的 fs 模块,但主进程…...
Kubernetes资源详解
华子目录 1.Kubernetes中的资源1.1资源管理介绍1.2资源管理方式1.2.1命令式对象管理1.2.2kubectl常见command命令1.2.3资源类型1.2.4常用资源类型 基本命令示例运行和调试命令示例高级命令示例总结 其他命令示例create和apply区别案例显示命名空间查看命名空间中的pod如何对外暴…...
C++11之线程
编译环境:Qt join:阻塞当前线程,直到线程函数退出 detach:将线程对象与线程函数分离,线程不依赖线程对象管理 注:join和detach两者必选其一,否则线程对象的回收会影响线程的回收,导致…...
界星空科技漆包线行业称重系统
万界星空科技为漆包线行业提供的称重系统是其MES制造执行系统解决方案中的一个重要组成部分。以下是对该系统的详细介绍: 一、系统概述 万界星空科技漆包线行业称重系统,是集成在MES系统中的一个功能模块,专门用于漆包线生产过程中的重量检…...
RabbitMQ的高级特性-事务
事务:RabbitMQ是基于AMQP协议实现的, 该协议实现了事务机制, 因此RabbitMQ也⽀持事务机制. SpringAMQP也提供了对事务相关的操作. RabbitMQ事务允许开发者确保消息的发送和接收是原⼦性的, 要么全部成功, 要么全部失败 配置事务管理器: Bean public Ra…...
Qt Linguist手册
概述 Qt 为将 Qt C 和 Qt Quick 应用程序翻译成当地语言提供了出色的支持。发布经理、翻译和开发人员可以使用 Qt 工具来完成他们的任务。 发布经理对应用程序的发布负总责。通常,他们负责协调开发人员和翻译人员的工作。他们可以使用 lupdate 工具同步源代码和翻…...
【简介Sentinel-1】
Sentinel-1是欧洲航天局哥白尼计划(GMES)中的地球观测卫星,由Sentinel-1A和Sentinel-1B两颗卫星组成。以下是对Sentinel-1的详细介绍: 一、基本信息 卫星名称:Sentinel-1 所属计划:欧洲航天局哥白尼计划…...
第 17 场小白入门赛蓝桥杯
第 17 场小白入门赛 2 北伐军费 发现每次选大的更优,所以可以排序之后,先手取右边,后手取左边。 实际发现,对于 A − B A-B A−B 的结果来说,后手对于这个式子的贡献是 − − a i --a_i −−ai ,也就…...
@antv/x6 导出图片下载,或者导出图片为base64由后端去处理。
1、导出为文件的格式,比如 PNG graph.exportPNG(function (dataURL) {console.log(dataURL);let img document.getElementById(img) as HTMLImageElement;img.src dataURL;},{backgroundColor: #fff,padding: [20, 20, 20, 20],quality: 1,width: graph.options.w…...
从零到精通:AI大模型的全方位学习路径解析,非常详细收藏我这一篇就够了
一、初聊大模型 1、什么是大模型? 大模型,通常指的是在人工智能领域中的大型预训练模型。你可以把它们想象成非常聪明的大脑,这些大脑通过阅读大量的文本、图片、声音等信息,学习到了世界的知识。这些大脑(模型&…...
PowerShell脚本在自动化Windows开发工作流程中的应用
PowerShell脚本在自动化Windows开发工作流程中的应用 在当今快速迭代的软件开发环境中,自动化已成为提高开发效率、减少人为错误、保障项目稳定性的重要手段。特别是在Windows平台上,PowerShell以其强大的脚本编写能力和对系统管理的深度集成࿰…...
【力扣 | SQL题 | 每日四题】力扣1783,1757,1747,1623,1468,1661
昨天晚上睡着了,今天把昨天的每日一题给补上。 1. 力扣1783:大满贯数量 1.1 题目: 表:Players ------------------------- | Column Name | Type | ------------------------- | player_id | int | | player_na…...
《深入探究 C++中的函数模板特化:开启编程新境界》
在 C的广袤世界中,函数模板特化是一项强大而富有魅力的技术,它为程序员提供了更高的灵活性和效率。本文将带你深入了解 C中函数模板特化是如何实现的,揭开这一神秘面纱,让你在编程之路上更上一层楼。 一、函数模板的基础概念 在…...
RTEMS面试题汇总及参考答案
目录 RTEMS是什么?它在嵌入式系统中扮演什么角色? RTEMS的全称是什么? RTEMS的主要特点有哪些? RTEMS支持哪些处理器架构? RTEMS的可剥夺型内核和不可剥夺型内核有何不同? RTEMS 的微内核设计及其优势 RTEMS 如何实现多任务处理和调度 RTEMS 的任务调度策略有哪…...
螺蛳壳里做道场:老破机搭建的私人数据中心---Centos下Docker学习03(网络及IP规划)
3 网络及IP规划 3.1 容器连接网络初步规划 规划所有容器与虚拟机的三张网卡以macvlan的方式进行连接(以后根据应用可以更改),在docker下创建nat、wifi、nei、wai四张网卡,他们和虚拟机及宿主机上NIC的相关连接参数如下表所示&am…...
BLOOM 模型的核心原理、局限与未来发展方向解析
1. 引言 1.1 BLOOM 模型概述 BLOOM(BigScience Large Open-science Open-access Multilingual Language Model)是一款由多个国际研究团队联合开发的大型语言模型。BLOOM 模型旨在通过先进的 Transformer 架构处理复杂的自然语言生成与理解任务。它支持…...
Kubernetes 深度洞察:重新认识 Docker 容器的奇妙世界
《Kubernetes 深度洞察:重新认识 Docker 容器的奇妙世界》 在 Kubernetes 的学习进程中,对 Docker 容器的深入理解至关重要。这一节,我们将重新认识 Docker 容器,探索其在 Kubernetes 生态系统中的关键作用。 一、Docker 容器的基本概念 Docker 容器是一种轻量级的虚拟化…...
柔性作业车间调度(FJSP)
1.1 调度问题的研究背景 生产调度是指针对一项可分解的工作(如产品制造),在尽可能满足工艺路线、资源情况、交货期等约束条件的前提下,通过下达生产指令,安排其组成部分(操作)所使用的资源、加工时间及加工的先后顺序,以获得产品制造时间或成本最优化的一项工作。 一般研究车间…...
速盾:游戏用CDN可以吗?
游戏用CDN是一种常见的解决方案,可以提高游戏的网络性能和加载速度。CDN(Content Delivery Network,内容分发网络)能够将游戏的静态资源分布到全球各地的边缘节点上,使用户可以从离他们最近的节点获取游戏资源…...
《重生到现代之从零开始的C语言生活》—— 字符函数和字符串函数
字符函数和字符串函数 字符分类函数 大家知道字符是分为很多种类型的 就比如说’a’ ‘1’ A’等等,所以我们需要一种函数来完成字符函数的分类 这就是字符分类函数 函数需要包含头文件<ctype.h> 函数的运行规则是:如果符合下列参数就返回真 …...
C++初阶-list的底层
目录 1.std::list实现的所有代码 2.list的简单介绍 2.1实现list的类 2.2_list_iterator的实现 2.2.1_list_iterator实现的原因和好处 2.2.2_list_iterator实现 2.3_list_node的实现 2.3.1. 避免递归的模板依赖 2.3.2. 内存布局一致性 2.3.3. 类型安全的替代方案 2.3.…...
CVPR 2025 MIMO: 支持视觉指代和像素grounding 的医学视觉语言模型
CVPR 2025 | MIMO:支持视觉指代和像素对齐的医学视觉语言模型 论文信息 标题:MIMO: A medical vision language model with visual referring multimodal input and pixel grounding multimodal output作者:Yanyuan Chen, Dexuan Xu, Yu Hu…...
脑机新手指南(八):OpenBCI_GUI:从环境搭建到数据可视化(下)
一、数据处理与分析实战 (一)实时滤波与参数调整 基础滤波操作 60Hz 工频滤波:勾选界面右侧 “60Hz” 复选框,可有效抑制电网干扰(适用于北美地区,欧洲用户可调整为 50Hz)。 平滑处理&…...
Golang 面试经典题:map 的 key 可以是什么类型?哪些不可以?
Golang 面试经典题:map 的 key 可以是什么类型?哪些不可以? 在 Golang 的面试中,map 类型的使用是一个常见的考点,其中对 key 类型的合法性 是一道常被提及的基础却很容易被忽视的问题。本文将带你深入理解 Golang 中…...
STM32+rt-thread判断是否联网
一、根据NETDEV_FLAG_INTERNET_UP位判断 static bool is_conncected(void) {struct netdev *dev RT_NULL;dev netdev_get_first_by_flags(NETDEV_FLAG_INTERNET_UP);if (dev RT_NULL){printf("wait netdev internet up...");return false;}else{printf("loc…...
Java多线程实现之Callable接口深度解析
Java多线程实现之Callable接口深度解析 一、Callable接口概述1.1 接口定义1.2 与Runnable接口的对比1.3 Future接口与FutureTask类 二、Callable接口的基本使用方法2.1 传统方式实现Callable接口2.2 使用Lambda表达式简化Callable实现2.3 使用FutureTask类执行Callable任务 三、…...
【Zephyr 系列 10】实战项目:打造一个蓝牙传感器终端 + 网关系统(完整架构与全栈实现)
🧠关键词:Zephyr、BLE、终端、网关、广播、连接、传感器、数据采集、低功耗、系统集成 📌目标读者:希望基于 Zephyr 构建 BLE 系统架构、实现终端与网关协作、具备产品交付能力的开发者 📊篇幅字数:约 5200 字 ✨ 项目总览 在物联网实际项目中,**“终端 + 网关”**是…...
QT: `long long` 类型转换为 `QString` 2025.6.5
在 Qt 中,将 long long 类型转换为 QString 可以通过以下两种常用方法实现: 方法 1:使用 QString::number() 直接调用 QString 的静态方法 number(),将数值转换为字符串: long long value 1234567890123456789LL; …...
ABAP设计模式之---“简单设计原则(Simple Design)”
“Simple Design”(简单设计)是软件开发中的一个重要理念,倡导以最简单的方式实现软件功能,以确保代码清晰易懂、易维护,并在项目需求变化时能够快速适应。 其核心目标是避免复杂和过度设计,遵循“让事情保…...
【Android】Android 开发 ADB 常用指令
查看当前连接的设备 adb devices 连接设备 adb connect 设备IP 断开已连接的设备 adb disconnect 设备IP 安装应用 adb install 安装包的路径 卸载应用 adb uninstall 应用包名 查看已安装的应用包名 adb shell pm list packages 查看已安装的第三方应用包名 adb shell pm list…...
