Electron笔记之进程间通信(ipc)
一、主进程和渲染进程
1.1 主进程和渲染进程的概念
在上手ipc通信之前,得对electron的进程模型有个基本的了解,electron中的进程大致可以分为主进程和渲染进程,主进程指的就是nodejs的进程,而渲染进程则可以简单的理解为一个Chromium的web页面。主进程,也就是nodejs进程只有一个,而渲染进程,也就是Chromium的web页面则可以有多个,ipc通信就是在主进程和渲染进程之间通信。
1.2 主进程和渲染进程的环境区别
认为主进程的代码是开发者自己写的,就是普通的node程序,但是渲染进程有可能会加载网页之类的,可能会执行第三方的js代码,渲染进程的权限是被限制了的,所以某些敏感操作就需要渲染进程给主进程发消息,让主进程去做,然后完事了再通知渲染进程。
在使用electron开发客户端程序的时候,将其类比为web端的B/S架构,其渲染进程就是前端的页面,是门面,而主进程则是服务器后台,负责处理一些与UI无关的业务逻辑,主进程和渲染进程不可避免的要进行一些数据、指令的交换,即这两个进程之间要通信交换数据,这就是进程间通信,electron提供了ipc模块用于在主进程和渲染进程之间通信。
二、主进程与渲染进程通信
2.1 渲染进程向主进程发送异步消息
渲染进程向主进程发送消息默认就是异步的,在渲染进程的html或者render.js中向主进程发送异步消息:
01 02 03 04 | const electron = require( "electron" ); // 第一个参数是约定的事件的名称,主进程要监听这个事件 // 第二个及之后的参数是要发送的具体的消息 electron.ipcRenderer.send( "render-to-main-message" , message); |
send方法至少需要两个参数,第一个是事件名称,在主线程中需要监听此事件,然后是至少一个参数的事件参数,可以有多个,但是至少有一个。
在主线程main.js中接收事件:
01 02 03 04 05 06 07 08 09 | // 接收从渲染进程发送到主进程的消息 ipcMain.on( "render-to-main-message" , (event, message) => { // 在控制台上打印一下 console.log(`receive message from render: ${message}`); // 回复消息 event.reply( "main-to-render-message" , `来自主进程:我收到了你的消息“${message}”`); }) |
使用 event.reply 在主进程中回复渲染进程发过来的消息,因为这个replay指定了一个事件名称,因此在渲染进程render.js中也要监听事件才能收到回复:
01 02 03 04 05 06 | // 接收主进程发来的消息 // 第一个参数是约定的事件的名称 // 第二个参数是处理事件的callback electron.ipcRenderer.on( "main-to-render-message" , (event, message) => { alert(message); }); |
2.2 渲染进程向主进程发送同步消息
同步消息是渲染进程向主进程发送的,因为渲染进程页面可以有多个,而主进程node进程只有一个,因此渲染进程可以等主进程,而主进程不能同步等渲染进程。
渲染进程向主进程发送同步消息,使用 electron.ipcRenderer.sendSync 方法,这个方法的返回值是从主进程中返回的,在渲染进程render.js中向主进程发送消息:
01 02 03 04 | const electron = require( "electron" ); // 发送同步消息 const replayMessage = electron.ipcRenderer.sendSync( "render-to-main-message-sync" , message); alert(replayMessage); |
在主进程main.js中接收并回复渲染进程发过来的同步消息:
01 02 03 04 05 06 07 08 09 | // 接收同步消息 ipcMain.on( "render-to-main-message-sync" , (event, message) => { // 控制台打印一下知道来了 console.log(`receive sync message from render: ${message}`); // 回复渲染进程的同步消息 event.returnValue = `来自主进程:我收到了你的消息“${message}”`; }) |
在主进程中对于同步消息和异步消息的接收没有区别,只是回复同步消息的时候变成了:
01 | event.returnValue = "要回复的消息内容" |
2.3 主进程向渲染进程发送消息
渲染进程可以向主进程发送同步消息或者异步消息,但是主进程只能向渲染进程发送异步消息,比如下面是在主进程启动后3秒向渲染进程发送一条消息:
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 | function createWindow() { const window = new BrowserWindow({ width: 800, height: 600, webPreferences: { nodeIntegration: true } }) // 注意这个路径是从项目根路径开始的 window.loadFile( "example/use-ipc/index.html" ) setTimeout(() => { window.webContents.send( "main-to-render-message" , "启动完成了" ); }, 3000) } |
在渲染进程render.js中监听此事件:
01 02 03 04 | const electron = require( "electron" ); electron.ipcRenderer.on( "main-to-render-message" , (event, message) => { alert(message); }); |
2.4 代码及运行效果一览
上面的三种发送方式都是只提取了部分代码做展示,完整的例子代码如下:
main.js:
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 | const {app, BrowserWindow, ipcMain} = require( "electron" ) function createWindow() { const window = new BrowserWindow({ width: 800, height: 600, webPreferences: { nodeIntegration: true } }) // 注意这个路径是从项目根路径开始的 window.loadFile( "example/use-ipc/index.html" ) setTimeout(() => { window.webContents.send( "main-to-render-message" , "启动完成了" ); }, 3000) } app.whenReady().then(createWindow) app.on( "window-all-closed" , () => { if (process.platform !== "darwin" ) { app.quit() } }) app.on( "activate" , () => { if (BrowserWindow.getAllWindows().length === 0) { createWindow() } }) // 接收从渲染进程发送到主进程的消息 ipcMain.on( "render-to-main-message" , (event, message) => { // 在控制台上打印一下 console.log(`receive message from render: ${message}`); // 回复消息 event.reply( "main-to-render-message" , `来自主进程:我收到了你的消息“${message}”`); }) // 接收同步消息 ipcMain.on( "render-to-main-message-sync" , (event, message) => { // 控制台打印一下知道来了 console.log(`receive sync message from render: ${message}`); // 回复渲染进程的同步消息 event.returnValue = `来自主进程:我收到了你的消息“${message}”`; }) |
index.html文件(render.js没有单独提出来,render的js直接放到html中了):
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | <! DOCTYPE html> < html lang="en"> < head > < meta charset="UTF-8"> < title >IPC通信</ title > </ head > < body > < h1 >IPC通信</ h1 > < input type="text" id="message"> < button onclick="sendMessageToMainProcess()">发送消息给主进程</ button > < script type="text/javascript"> const electron = require("electron"); // 接收主进程发来的消息 // 第一个参数是约定的事件的名称 // 第二个参数是处理事件的callback electron.ipcRenderer.on("main-to-render-message", (event, message) => { alert(message); }); // 向主进程发送消息 function sendMessageToMainProcess() { const message = document.getElementById("message").value; // 第一个参数是约定的事件的名称,主进程要监听这个事件 // 第二个及之后的参数是要发送的具体的消息 electron.ipcRenderer.send("render-to-main-message", message); // 发送同步消息 const replayMessage = electron.ipcRenderer.sendSync("render-to-main-message-sync", message); alert(replayMessage); } </ script > </ body > </ html > |
效果:
本文所用Electron版本:"electron": "^11.1.0"
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 提示词工程——AI应用必不可少的技术
· Open-Sora 2.0 重磅开源!
· 周边上新:园子的第一款马克杯温暖上架
2020-01-17 vulnhub靶机之Me and My Girlfriend: 1