当前位置: 首页 > news >正文

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 提供了 ipcMainipcRenderer 模块用于主进程和渲染进程之间的通信。
    • 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.send API 也可用于双向通信。在 Electron 7 之前,官方推荐使用 ipcRenderer.send 进行异步双向通信。在 Electron 7 中,官方添加 ipcRenderer.invoke API,用于处理渲染器进程中双向 IPC。
  • ipcMain.on(channel, listener)

    • 在主进程中监听来自渲染进程的特定通道消息。
    • hannel:这是一个字符串,表示特定的通信通道名称。渲染进程使用相同的通道名称通过 ipcRenderer.sendipcRenderer.invoke 向主进程发送消息。
    • listener:这是一个回调函数,当主进程接收到来自渲染进程通过指定通道发送的消息时,这个回调函数会被执行。
      • 回调函数通常接受两个参数:eventargsevent 代表事件对象,可用于回复渲染进程等操作;args 是渲染进程发送的参数,可以是单个值或一组值,具体取决于渲染进程的发送方式。

示例:

实现需求:点击按钮后,在⽤户的 D 盘创建⼀个 hello.txt ⽂件,⽂件内容来⾃于⽤户输⼊。

  1. 在页面中添加相关元素
<!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>
  1. preload.js 中使⽤ ipcRenderer.send('信道', 参数) 发送消息,与主进程通信。
// contextBridge:在隔离的上下文中创建一个安全的、双向的、同步的桥梁。
// ipcRenderer是渲染进程中用于与主进程进行通信的模块。
const {contextBridge, ipcRenderer} = require('electron')// 把方法/数据暴露给渲染进程
contextBridge.exposeInMainWorld('customAPI', {saveFile: data => {// 渲染进程给主进程发送⼀个消息ipcRenderer.send('save-file', data)}
})
  1. 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);
});
  1. 主进程中,在加载页面之前,使用 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');
}

渲染进程与主进程通信的流程

  1. 渲染进程触发:
    • 当渲染进程中的某个事件发生时,比如用户点击按钮或页面加载完成,可以调用 ipcRenderer.send('信道', 参数) 方法向主进程发送消息。
  2. 主进程接收和处理:
    • 主进程使用 ipcMain.on('信道', 回调) 方法监听特定的通道名称。当主进程接收到来自渲染进程的消息时,它可以根据通道名称和传递的参数执行相应的操作。
  3. 渲染进程接收回复:
    • 渲染进程可以使用 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:一个回调函数,当主进程接收到来自渲染进程通过指定通道发送的同步请求时,这个回调函数会被执行。
      • 回调函数通常接受两个参数:eventargsevent 代表事件对象,可用于回复渲染进程等操作;args 是渲染进程发送的参数,可以是单个值或一组值,具体取决于渲染进程的发送方式。
      • 回调函数需要返回一个值,这个值将作为响应发送回渲染进程。

示例:

实现需求:点击按钮从 D 盘读取 hello.txt 中的内容,并将结果呈现在页面上。

  1. 在页面中添加相关元素
<div id="content"></div>
<button id="btn">读取⽤户D盘的hello.txt</button
  1. preload.js 中使⽤ ipcRenderer.invoke('信道', 参数) 发送消息,与主进程通信。
// contextBridge:在隔离的上下文中创建一个安全的、双向的、同步的桥梁。
// ipcRenderer是渲染进程中用于与主进程进行通信的模块。
const {contextBridge, ipcRenderer} = require('electron')// 把方法/数据暴露给渲染进程
contextBridge.exposeInMainWorld('customAPI', {readFile: () => {// invoke 的返回值永远是Promisereturn ipcRenderer.invoke('read-file')}
})
  1. 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
});
  1. 主进程中,在加载页面之前,使用 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-replyasynchronous-message 通道的回复结果。如果通过这些通道非常频繁地来回传递消息,则需要添加其他应用代码来单独跟踪每个调用和响应。

模式3:主进程到渲染器进程

概述:主进程使用 win.webContents.send 发送消息,渲染进程使⽤ ipcRenderer.on 接收并处理消
息。
常用于:从主进程主动发送消息到渲染器进程。

示例:

需求:应⽤加载 6 秒钟后,主动给渲染进程发送⼀个消息

  1. 主进程中,使⽤ 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);
}
  1. preload.js 中使⽤ ipcRenderer.on ('信道', 回调) 接收消息,并配置回调函数。
window.onload = () => {customAPI.getMessage(logMessage);
};
function logMessage(event, str) {console.log(event, str);
}

相关文章:

Electron 进程通信

预加载&#xff08;preload&#xff09;脚本只能访问部分 Node.js API&#xff0c;但是主进程可以访问全部API。此时&#xff0c;需要使用进程通信。 比如&#xff0c;在preload.js中&#xff0c;不能访问__dirname&#xff0c;不能使用 Node 中的 fs 模块&#xff0c;但主进程…...

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之线程

编译环境&#xff1a;Qt join&#xff1a;阻塞当前线程&#xff0c;直到线程函数退出 detach&#xff1a;将线程对象与线程函数分离&#xff0c;线程不依赖线程对象管理 注&#xff1a;join和detach两者必选其一&#xff0c;否则线程对象的回收会影响线程的回收&#xff0c;导致…...

界星空科技漆包线行业称重系统

万界星空科技为漆包线行业提供的称重系统是其MES制造执行系统解决方案中的一个重要组成部分。以下是对该系统的详细介绍&#xff1a; 一、系统概述 万界星空科技漆包线行业称重系统&#xff0c;是集成在MES系统中的一个功能模块&#xff0c;专门用于漆包线生产过程中的重量检…...

RabbitMQ的高级特性-事务

事务&#xff1a;RabbitMQ是基于AMQP协议实现的, 该协议实现了事务机制, 因此RabbitMQ也⽀持事务机制. SpringAMQP也提供了对事务相关的操作. RabbitMQ事务允许开发者确保消息的发送和接收是原⼦性的, 要么全部成功, 要么全部失败 配置事务管理器&#xff1a; Bean public Ra…...

Qt Linguist手册

概述 Qt 为将 Qt C 和 Qt Quick 应用程序翻译成当地语言提供了出色的支持。发布经理、翻译和开发人员可以使用 Qt 工具来完成他们的任务。 发布经理对应用程序的发布负总责。通常&#xff0c;他们负责协调开发人员和翻译人员的工作。他们可以使用 lupdate 工具同步源代码和翻…...

【简介Sentinel-1】

Sentinel-1是欧洲航天局哥白尼计划&#xff08;GMES&#xff09;中的地球观测卫星&#xff0c;由Sentinel-1A和Sentinel-1B两颗卫星组成。以下是对Sentinel-1的详细介绍&#xff1a; 一、基本信息 卫星名称&#xff1a;Sentinel-1 所属计划&#xff1a;欧洲航天局哥白尼计划…...

第 17 场小白入门赛蓝桥杯

第 17 场小白入门赛 2 北伐军费 发现每次选大的更优&#xff0c;所以可以排序之后&#xff0c;先手取右边&#xff0c;后手取左边。 实际发现&#xff0c;对于 A − B A-B A−B 的结果来说&#xff0c;后手对于这个式子的贡献是 − − a i --a_i −−ai​ &#xff0c;也就…...

@antv/x6 导出图片下载,或者导出图片为base64由后端去处理。

1、导出为文件的格式&#xff0c;比如 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、什么是大模型&#xff1f; 大模型&#xff0c;通常指的是在人工智能领域中的大型预训练模型。你可以把它们想象成非常聪明的大脑&#xff0c;这些大脑通过阅读大量的文本、图片、声音等信息&#xff0c;学习到了世界的知识。这些大脑&#xff08;模型&…...

PowerShell脚本在自动化Windows开发工作流程中的应用

PowerShell脚本在自动化Windows开发工作流程中的应用 在当今快速迭代的软件开发环境中&#xff0c;自动化已成为提高开发效率、减少人为错误、保障项目稳定性的重要手段。特别是在Windows平台上&#xff0c;PowerShell以其强大的脚本编写能力和对系统管理的深度集成&#xff0…...

【力扣 | SQL题 | 每日四题】力扣1783,1757,1747,1623,1468,1661

昨天晚上睡着了&#xff0c;今天把昨天的每日一题给补上。 1. 力扣1783&#xff1a;大满贯数量 1.1 题目&#xff1a; 表&#xff1a;Players ------------------------- | Column Name | Type | ------------------------- | player_id | int | | player_na…...

《深入探究 C++中的函数模板特化:开启编程新境界》

在 C的广袤世界中&#xff0c;函数模板特化是一项强大而富有魅力的技术&#xff0c;它为程序员提供了更高的灵活性和效率。本文将带你深入了解 C中函数模板特化是如何实现的&#xff0c;揭开这一神秘面纱&#xff0c;让你在编程之路上更上一层楼。 一、函数模板的基础概念 在…...

RTEMS面试题汇总及参考答案

目录 RTEMS是什么?它在嵌入式系统中扮演什么角色? RTEMS的全称是什么? RTEMS的主要特点有哪些? RTEMS支持哪些处理器架构? RTEMS的可剥夺型内核和不可剥夺型内核有何不同? RTEMS 的微内核设计及其优势 RTEMS 如何实现多任务处理和调度 RTEMS 的任务调度策略有哪…...

螺蛳壳里做道场:老破机搭建的私人数据中心---Centos下Docker学习03(网络及IP规划)

3 网络及IP规划 3.1 容器连接网络初步规划 规划所有容器与虚拟机的三张网卡以macvlan的方式进行连接&#xff08;以后根据应用可以更改&#xff09;&#xff0c;在docker下创建nat、wifi、nei、wai四张网卡&#xff0c;他们和虚拟机及宿主机上NIC的相关连接参数如下表所示&am…...

BLOOM 模型的核心原理、局限与未来发展方向解析

1. 引言 1.1 BLOOM 模型概述 BLOOM&#xff08;BigScience Large Open-science Open-access Multilingual Language Model&#xff09;是一款由多个国际研究团队联合开发的大型语言模型。BLOOM 模型旨在通过先进的 Transformer 架构处理复杂的自然语言生成与理解任务。它支持…...

Kubernetes 深度洞察:重新认识 Docker 容器的奇妙世界

《Kubernetes 深度洞察:重新认识 Docker 容器的奇妙世界》 在 Kubernetes 的学习进程中,对 Docker 容器的深入理解至关重要。这一节,我们将重新认识 Docker 容器,探索其在 Kubernetes 生态系统中的关键作用。 一、Docker 容器的基本概念 Docker 容器是一种轻量级的虚拟化…...

柔性作业车间调度(FJSP)

1.1 调度问题的研究背景 生产调度是指针对一项可分解的工作(如产品制造),在尽可能满足工艺路线、资源情况、交货期等约束条件的前提下,通过下达生产指令,安排其组成部分(操作)所使用的资源、加工时间及加工的先后顺序,以获得产品制造时间或成本最优化的一项工作。 一般研究车间…...

速盾:游戏用CDN可以吗?

游戏用CDN是一种常见的解决方案&#xff0c;可以提高游戏的网络性能和加载速度。CDN&#xff08;Content Delivery Network&#xff0c;内容分发网络&#xff09;能够将游戏的静态资源分布到全球各地的边缘节点上&#xff0c;使用户可以从离他们最近的节点获取游戏资源&#xf…...

《重生到现代之从零开始的C语言生活》—— 字符函数和字符串函数

字符函数和字符串函数 字符分类函数 大家知道字符是分为很多种类型的 就比如说’a’ ‘1’ A’等等&#xff0c;所以我们需要一种函数来完成字符函数的分类 这就是字符分类函数 函数需要包含头文件<ctype.h> 函数的运行规则是&#xff1a;如果符合下列参数就返回真 …...

双指针:滑动窗口

题目描述 给定两个字符串 S 和 T&#xff0c;求 S 中包含 T 所有字符的最短连续子字符串的长度&#xff0c;同时要求时间复杂度不得超过 O(n)。 输入输出样例 输入是两个字符串 S 和 T&#xff0c;输出是一个 S 字符串的子串。样例如下&#xff1a; 在这个样例中&#xff0c…...

云原生(四十八) | Nginx软件安装部署

文章目录 Nginx软件安装部署 一、Nginx软件部署步骤 二、安装与配置Nginx Nginx软件安装部署 一、Nginx软件部署步骤 第一步&#xff1a;安装 Nginx 软件 第二步&#xff1a;把 Nginx 服务添加到开机启动项 第三步&#xff1a;配置 Nginx 第四步&#xff1a;启动Nginx …...

【WPF开发】如何设置窗口背景颜色以及背景图片

在WPF中&#xff0c;可以通过设置窗口的 Background 属性来改变窗口的背景。以下是一些设置窗口背景的不同方法&#xff1a; 一、设置纯色背景 1、可以使用 SolidColorBrush 来设置窗口的背景为单一颜色。 <Window x:Class"YourNamespace.MainWindow"xmlns&quo…...

USB 3.0?USB 3.1?USB 3.2?怎么区分?

还记得小白刚接触电脑的时候&#xff0c;电脑普及的USB接口大部分是USB 2.0&#xff0c;还有少部分USB 1.0的&#xff08;现在基本上找不到了&#xff09;。 当时的电脑显示器&#xff0c;可能00后的小伙伴都没见过&#xff0c;它们大概长这样&#xff1a; 当时小白以为电脑最…...

Gitlab实战教程:打造企业级代码托管与协作平台!

目录 一、Gitlab概述1、Gitlab简介&#xff08;1&#xff09;Gitlab的定义&#xff08;2&#xff09;Gitlab与Git的关系&#xff08;3&#xff09;Gitlab的主要功能 2、Gitlab与Git的关系&#xff08;1&#xff09;Git的基本概念&#xff08;2&#xff09;Gitlab与Git的关联&am…...

更新C语言题目

1.以下程序输出结果是() int main() {int a 1, b 2, c 2, t;while (a < b < c) {t a;a b;b t;c--;}printf("%d %d %d", a, b, c); } 解析:a1 b2 c2 a<b 成立 ,等于一个真值1 1<2 执行循环体 t被赋值为1 a被赋值2 b赋值1 c-- c变成1 a<b 不成立…...

struct和C++的类

1.铺垫 1.1想看明白这章节&#xff0c;必须要懂得C语言的struct结构体、C语言深度解剖的static用法、理解声明与定义&#xff0c;C的类和static用法&#xff1b;否则看起来有些吃力 2.引子 2.1struct结构体里面只能存储内置类型&#xff1b;比如&#xff1a;char、short、 i…...

【数据结构与算法】LeetCode:图论

文章目录 LeetCode&#xff1a;图论岛屿数量&#xff08;Hot 100&#xff09;岛屿的最大面积腐烂的橘子&#xff08;Hot 100&#xff09;课程表&#xff08;Hot 100&#xff09; LeetCode&#xff1a;图论 岛屿数量&#xff08;Hot 100&#xff09; 岛屿数量 DFS: class So…...

YOLOv8 基于NCNN的安卓部署

YOLOv8 NCNN安卓部署 前两节我们依次介绍了基于YOLOv8的剪枝和蒸馏 本节将上一节得到的蒸馏模型导出NCNN&#xff0c;并部署到安卓。 NCNN 导出 YOLOv8项目中提供了NCNN导出的接口&#xff0c;但是这个模型放到ncnn-android-yolov8项目中你会发现更换模型后app会闪退。原因…...

【Python|接口自动化测试】使用requests发送http请求时添加headers

文章目录 1.前言2.HTTP请求头的作用3.在不添加headers时4.反爬虫是什么&#xff1f;5.在请求时添加headers 1.前言 本篇文章主要讲解如何使用requests请求时添加headers&#xff0c;为什么要加headers呢&#xff1f;是因为有些接口不添加headers时&#xff0c;请求会失败。 2…...