ARTICLE DETAIL

资讯详情

深耕编程入门与网站建设的一线实战洞察。

Electron IpcRendererEvent:渲染进程 IPC 事件对象详解

Electron IpcRendererEvent:渲染进程 IPC 事件对象详解 Electron IpcRendererEvent渲染进程 IPC 事件对象详解【免费下载链接】electron:electron: Build cross-platform desktop apps with JavaScript, HTML, and CSS项目地址: https://gitcode.com/GitHub_Trending/el/electronIpcRendererEvent是 Electron 渲染进程中接收 IPC 消息时回调的第一个参数它继承自标准的Event并额外携带sender与ports两个关键属性。掌握这个对象你就能够理解 Electron 渲染进程侧 IPC 事件是如何从原生层派发到 JavaScript 监听器的知道如何通过event.sender向发送来源回传消息、通过event.ports获取随消息转移的MessagePort并了解为什么在安全场景下绝不能把这个event暴露给不受信任的网页内容。什么是 IpcRendererEvent根据 结构定义文档IpcRendererEvent对象继承自Event即 Node.js 的 EventEmitter 事件基类因此它具备type、target等标准事件成员同时被扩展出两个 Electron 专属属性senderIpcRenderer——原始发出该事件的IpcRenderer实例ports[MessagePort][]——随本条消息一起转移transfer过来的MessagePort列表。它是 ipcRenderer 模块所有监听方法中回调签名的固定首参。在ipcRenderer的 API 文档中ipcRenderer.on(channel, listener)、ipcRenderer.off(channel, listener)、ipcRenderer.once(channel, listener)、ipcRenderer.addListener(channel, listener)与ipcRenderer.removeListener(channel, listener)均声明监听器签名为(event: IpcRendererEvent, ...args: any[])当channel上有新消息到达时监听器会以listener(event, ...args)的形式被调用其中event就是IpcRendererEvent...args是对端通过结构化克隆算法序列化后解开的消息负载。属性一sender —— 事件的“回程票”sender持有发出该事件的IpcRenderer实例。它的实用价值在于渲染进程收到主进程或其他进程经内部通道发来的消息后可以借助它把响应发回发送方而无需预先约定一个回传频道。仓库内部实现正是这样使用sender的。ipc-renderer-internal-utils.ts 中定义了内部 IPC 的处理器类型与handle函数type IPCHandler (event: Electron.IpcRendererEvent, ...args: any[]) any; export const handle function T extends IPCHandler(channel: string, handler: T) { ipcRendererInternal.on(channel, async (event, requestId, ...args) { const replyChannel ${channel}_RESPONSE_${requestId}; try { event.sender.send(replyChannel, null, await handler(event, ...args)); } catch (error) { event.sender.send(replyChannel, error); } }); };这段代码展示了 Electron 内部实现invoke式请求/响应模式的典型手法监听器通过event.sender.send(...)把结果或错误发回给发起请求的一方回传频道名由${channel}_RESPONSE_${requestId}动态拼接而成。对于应用代码同样的模式意味着你可以用sender实现“谁发来的消息就回给谁”的点对点应答而不必在频道命名里硬编码来源信息。属性二ports —— 随消息转移的 MessagePortports属性是一个MessagePort的二维数组MessagePort[][]保存随这条 IPC 消息一起转移过来的MessagePort端口。MessagePort是浏览器平台标准的结构化并口可用postMessage在其上通信Electron 允许在 IPC 通道中把端口转移给对端从而在主进程与渲染进程之间建立一条独立的、双向的高速通信链路绕开频道式的逐条消息模型。配合ipcRenderer.on使用你可以在监听器里直接取出event.ports并调用port.postMessage(...)、port.start()开始通信。更多端口编程细节可参考 MessagePort 教程 及 IPC 教程。源码级视角IpcRendererEvent 是如何被构造和派发的从源码结构看IpcRendererEvent并不是一个真正的原生事件类而是在 JS 层被组装成一个普通事件参数对象后随emit传出的。关键实现位于 ipc-native-setup.tsconst v8Util process._linkedBinding(electron_common_v8_util); // ElectronApiServiceImpl will look for the ipcNative hidden object when // invoking the onMessage callback. v8Util.setHiddenValue(globalThis, ipcNative, { onMessage(internal: boolean, channel: string, ports: MessagePort[], args: any[]) { const sender internal ? ipcRendererInternal : ipcRenderer; sender.emit(channel, { sender, ports }, ...args); } });可以读出三个要点原生 IPC 层ElectronApiServiceImpl收到消息后会通过 V8 隐藏值机制找到挂在globalThis上的ipcNative隐藏对象并回调其onMessageonMessage收到的原生参数包括channel、ports、args以及一个区分内部/外部消息的internal标志JS 层随后以sender.emit(channel, { sender, ports }, ...args)派发事件——第一个参数对象{ sender, ports }就是用户代码中拿到的IpcRendererEvent同时它又被作为 EventEmitter 的Event语义载体传入监听器。这也解释了为什么存在“内部”与“外部”两套ipcRendereripcRendererInternal见 ipc-renderer-internal.ts承载 Electron 自身框架消息ipcRenderer承载应用消息两者派发到不同监听集合但共享同一套{ sender, ports }事件组装逻辑。典型用法示例一个完整的、可直接运行的最小示例preload 或渲染进程上下文隔离关闭的场景const { ipcRenderer } require(electron); ipcRenderer.on(task-status, (event, ...args) { const [progress, message] args; // event: IpcRendererEvent console.log(event.type); // task-status继承自 Event console.log(event.sender); // 发出事件的 IpcRenderer 实例 console.log(event.ports); // 随消息转移的 MessagePort 列表 // 借助 sender 向来源回传确认 event.sender.send(task-status-ack, progress); }); // 只响应一次 ipcRenderer.once(one-shot, (event, payload) { console.log(payload, event.ports); });如果监听后需要解除绑定使用ipcRenderer.off(channel, listener)或ipcRenderer.removeListener(channel, listener)二者等价ipcRenderer.once注册的监听器在下次该频道收到消息后即自动移除。安全注意事项不要把 event 暴露给网页ipcRenderer 文档 中有一段明确的警告出于安全原因不要将event参数暴露给渲染器指经contextBridge暴露给不可信网页内容。正确的做法是把来自渲染器的回调包一层只传递业务参数// 错误把整个 event 交给网页 ipcRenderer.on(my-channel, (event, ...args) callback(event, ...args)); // 正确包装一层只转发业务参数 ipcRenderer.on(my-channel, (event, ...args) callback(...args));原因是IpcRendererEvent上的sender是一个完整的IpcRenderer实例若它被不可信网页内容拿到等于把“可向任意 IPC 频道发送消息”的能力交了出去可能形成任意通道注入。安全指南 同样强调IPC 事件回调参数是一个IpcRendererEvent对象包含sender等敏感属性暴露它会把危险的 Electron API 带到渲染进程一侧。历史演进被移除的属性值得注意的是IpcRendererEvent曾经还带有senderId与senderIsMainFrame两个属性。根据 breaking-changes.md这两个属性先被弃用、随后连同相关 API 一起被彻底移除不再出现在当前版本的IpcRendererEvent结构定义中。如果你的旧代码中引用了event.senderId应当改为直接使用event.sender上的实例方法来判断与应答。小结IpcRendererEvent体量虽小却是 Electron 渲染进程 IPC 编程的枢纽sender提供了指向发送来源IpcRenderer实例的回程通道ports承载了随消息转移的MessagePort而继承自Event的基类语义则让你能按标准 EventEmitter 方式监听、解绑。结合 ipc-native-setup.ts 中onMessage的派发逻辑可以完整理解“原生消息 → 隐藏值回调 →{ sender, ports }事件对象 → 监听器”这条链路并据此写出既高效又符合 Electron 安全模型的 IPC 代码。【免费下载链接】electron:electron: Build cross-platform desktop apps with JavaScript, HTML, and CSS项目地址: https://gitcode.com/GitHub_Trending/el/electron创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表