简介
在 Electron 应用程序中,MessagePorts 是一种允许在不同上下文之间传递消息的机制。它类似于 window.postMessage 机制,但是在不同的通道上工作。本教程将详细介绍 MessagePorts 的概念、使用方法和示例代码。
MessagePorts 概念
MessagePorts 是成对创建的,消息发送到一个端口将被另一个端口接收。它们可以用于在不同上下文之间通信,例如主进程和渲染进程之间,或者不同渲染进程之间。
在主进程中的 MessagePorts
由于主进程不是一个网页,因此它不具有原生的 MessagePort 和 MessageChannel 类。Electron 添加了 MessagePortMain 和 MessageChannelMain 类来处理主进程中的 MessagePorts。
close 事件
Electron 还添加了一个 close 事件到 MessagePort 对象上,该事件在通道的另一端关闭时触发。
示例用例
1. 在两个渲染进程之间设置 MessageChannel
在这个示例中,我们将创建一个 MessageChannel,并将其传递给两个渲染进程。然后,我们将在两个渲染进程之间发送消息。
// 主进程
const { MessageChannel } = require('electron');
let channel = new MessageChannel();
let port1 = channel.port1;
let port2 = channel.port2;
// 将 port1 传递给渲染进程 1
win1.webContents.send('set-port', port1);
// 将 port2 传递给渲染进程 2
win2.webContents.send('set-port', port2);
// 渲染进程 1
ipcRenderer.on('set-port', (event, port) => {
port.postMessage('Hello from renderer 1!');
});
// 渲染进程 2
ipcRenderer.on('set-port', (event, port) => {
port.onmessage = (event) => {
console.log(`Received message from renderer 1: ${event.data}`);
};
});
2. 使用 MessageChannel 与隐藏的 "worker" 进程通信
在这个示例中,我们将创建一个隐藏的 "worker" 进程,并使用 MessageChannel 与其通信。
// 主进程
const { BrowserWindow } = require('electron');
let workerWin = new BrowserWindow({
show: false,
webPreferences: {
nodeIntegration: true
}
});
let channel = new MessageChannel();
let port1 = channel.port1;
let port2 = channel.port2;
workerWin.webContents.send('set-port', port2);
// 主进程
port1.postMessage('Hello from main process!');
// 工作进程
ipcRenderer.on('set-port', (event, port) => {
port.onmessage = (event) => {
console.log(`Received message from main process: ${event.data}`);
};
});
3. 使用 MessageChannel 实现 "response stream"
在这个示例中,我们将使用 MessageChannel 实现一个 "response stream",其中单个请求可以响应一个数据流。
// 主进程
const { MessageChannel } = require('electron');
let channel = new MessageChannel();
let port1 = channel.port1;
let port2 = channel.port2;
// 将 port1 传递给渲染进程
win.webContents.send('set-port', port1);
// 渲染进程
ipcRenderer.on('set-port', (event, port) => {
port.postMessage('Request data!');
port.onmessage = (event) => {
console.log(`Received data: ${event.data}`);
};
});
// 主进程
port2.onmessage = (event) => {
let data = ['data1', 'data2', 'data3'];
data.forEach((item) => {
port2.postMessage(item);
});
};
4. 直接在主进程和渲染进程之间通信
在这个示例中,我们将直接在主进程和渲染进程之间使用 MessageChannel 进行通信。
// 主进程
const { MessageChannel } = require('electron');
let channel = new MessageChannel();
let port1 = channel.port1;
let port2 = channel.port2;
// 将 port1 传递给渲染进程
win.webContents.send('set-port', port1);
// 渲染进程
ipcRenderer.on('set-port', (event, port) => {
port.postMessage('Hello from renderer!');
port.onmessage = (event) => {
console.log(`Received message from main process: ${event.data}`);
};
});
// 主进程
port2.onmessage = (event) => {
console.log(`Received message from renderer: ${event.data}`);
port2.postMessage('Hello from main process!');
};
结论
MessagePorts 是 Electron 应用程序中的一种强大机制,允许在不同上下文之间传递消息。通过本教程,您应该已经了解了 MessagePorts 的概念、使用方法和示例代码。