【Electron】IpcMainEvent 参数使用总结
·
IPCMain 介绍:
IPCMain 从主进程到渲染进程的异步通信,要想与渲染进程通信,则需通过preload配置通信桥。
IpcRenderer 从渲染进程到主进程的异步通信。
通信桥:
contextBridge.exposeInMainWorld(
'electron': {
ipcRenderer: {
...ipcMain.API
}
}
)
IpcMainEvent 参数总结:
- type 字符串
- 可能的值包括frame
事件类型
// 示例值
event.type = "frame";
// 可能的其他值:根据实际应用可能还有 "window", "dialog" 等
processId Integer
- 发送该消息的渲染进程内部的ID
**渲染进程 ID**
// 示例值
event.processId = 12345;
// 这标识了发送消息的渲染进程的唯一ID
frameId Integer
- 发送该消息的渲染进程框架的ID(可能是iframe)
渲染进程框架 ID
// 示例值
event.frameId = 1; // 主框架
// 或
event.frameId = 2; // iframe框架
returnValue any
- 如果对此赋值,则该值会在同步消息中返回
同步消息返回值
// 示例:在同步IPC消息中设置返回值
event.returnValue = "操作成功";
// 或
event.returnValue = { data: "返回的数据", status: "success" };
示例:
主进程:
ipcMain.on('channel-name', (event, data) => {
event.returnValue = '消息'
})
渲染进程:必须要用sendSync才能获取到内容
const getValue = ipcRenderer.sendSync('channel-name')
console.log(getValue) // 消息
sender WebContents
- 返回webContents 发送消息的内容
发送消息的WebContents
sender.webContents = BrowserWindow.webContents
示例(异步):
// 主进程
ipcMain.on('channel-name', (event: Electron.IpcMainEvent, data) => {
console.log('收到消息:', data)
event.sender.send('response-channel', {
status: 'success',
message: '处理完成',
result: data * 2
})
})
// 渲染进程
ipcRenderer.send(
'channel-name',
50
)
ipcRenderer.on('response-channel', (getValue: any) => {
console.log(getValue)
结果:{
"status": "success",
"message": "处理完成",
"result": 100
}
})
senderFrame WebFrameMain | null只读
- 发送此消息的帧。null 如果在帧已导航或已销毁后访问此消息,则可能为空。
发送消息的框架
// 示例:检查发送框架
if (event.senderFrame) {
console.log(event.senderFrame.url); // 框架的URL
} else {
console.log("框架已销毁或不存在");
}
ports MessagePortMain []
- 此消息传输的消息端口列表
使用场景:
MessagePort 是需要“专线高速公路”时才会用的。普通路(IPC)不够用时再用它
官方推荐使用MessagePort的典型场景:
- 高吞吐消息
- 长连接
- 设备驱动
- 日志流
- WebRTC媒体包通信
- 持续大量事件流
若是高频业务(如:蓝牙流、TCP流、日志)必须要独立一个MessageChannelMain()
// 主进程
const chBLE = new MessageChannelMain();
const chTCP = new MessageChannelMain();
const chLog = new MessageChannelMain();
// preload
ipcRenderer.on('port-ble', (e) => window.postMessage('port-ble', '*', e.ports));
ipcRenderer.on('port-tcp', (e) => window.postMessage('port-tcp', '*', e.ports));
ipcRenderer.on('port-log', (e) => window.postMessage('port-log', '*', e.ports));
// channel
window.addEventListener("message", (e) => {
if (e.data === "port-ble") setupBLE(e.ports[0]);
if (e.data === "port-tcp") setupTCP(e.ports[0]);
});
实践代码示例:
参考:https://gist.github.com/johannesgiani/a27fab2121dadb1b37820e891dac0aaf
# main 方法
import chalk from 'chalk';
import { MessageChannelMain } from 'electron';
class ChannelMessageManager {
webContents: Electron.WebContents;
channel: MessageChannelMain;
portToRenderer: Electron.MessagePortMain;
port: Electron.MessagePortMain | null;
constructor(mainWindow: Electron.WebContents) {
this.webContents = mainWindow;
this.port = null;
// 标注:最初采用了did-finish-load , 或者ipcMain.on,在preload通信桥中写全局调用,然后想在渲染进程直接调用window.on('message', (event) => console.log(event));但都会在渲染进程更新时容易丢掉通信通道,所以采用目前这套方案是目前最稳妥的
ipcMain.on('main-to-render-message', (event) => {
// 创建消息通道
const { port1, port2 } = new MessageChannelMain();
this.port = port1;
this.messageChannel()
event.sender.postMessage(
'send-message',
{ type: 'main-ready' },
[port2]
)
}
}
messageChannel() {
// render to main message
this.port1.on('message', (event) => {
console.log(chalk.bgGreenBright('[main] got from renderer:'), event.data);
// mian send message to render
this.port1.postMessage({ from: 'main', echo: 'initialized' });
});
}
}
export default ChannelMessageManager;
# preload js
/** 设置消息通道 */
setupMessageChannel(callback?: (...args: unknown[]) => void) {
ipcRenderer.send('main-to-render-message')
const subscription = (event: IpcRendererEvent) => {
const port = event.ports[0];
port.onmessage = (messageEvent) => {
callback && callback(messageEvent.data)
}
(window as any).messagePort = port
}
ipcRenderer.on('message', subscription);
return () => {
ipcRenderer.removeListener('message', subscription);
}
},
/** 通过消息通道发送消息 */
postMessageToPort(message: any) {
(window as any)?.messagePort.postMessage(message);
}
# 渲染进程
ipcRenderer.setupMessageChannel((data) => {
console.log('收到渲染进程消息:', data)
})
setTimeout(() => {
// 发送数据
ipcRenderer.postMessageToPort({
type: 'scan-start',
data: 5000
})
}, 500);
reply Function
将 IPC 消息发送到渲染器框架的函数,该渲染器框架发送当前正在处理的原始消息。 您应该使用“reply”方法回复发送的消息,以确保回复将转到正确的进程和框架。
channel 细绳
…args 任何[]
#异步消息处理
## 主进程
ipcMain.on('channel-name', (event, data) => {
console.log('收到消息:', data)
// 使用 reply 方法回复
event.reply('response-channel', {
status: 'success',
message: '处理完成',
result: data * 2
})
})
## 渲染进程
// 异步消息
ipcRenderer.send('channel-name', 5)
ipcRenderer.on('response-channel', (response) => { // 注意参数,我这里的preload配置没有传送回来event
console.log('收到回复:', response) // {status: 'success', message: '处理完成', result: 10}
})
#同步消息处理
## 主进程
ipcMain.on('sync-calculation', (event, data) => {
console.log('同步计算请求:', data)
// 对于同步消息,设置 returnValue
if (data.operation === 'add') {
event.returnValue = data.a + data.b
} else if (data.operation === 'multiply') {
event.returnValue = data.a * data.b
} else {
event.returnValue = null
}
})
## 渲染进程
// 同步消息
const result = ipcRenderer.sendSync('sync-calculation', {
operation: 'add',
a: 10,
b: 20
})
console.log('同步结果:', result) // 30
更多推荐


所有评论(0)