Problem:
While working on an Electron program that has multiple windows, I knew I needed the windows to be able to talk to each other. This is usually done with each window establishing a connection with the main script, and then the main script facilitating the communication between each window. This way works fine, but seems very manual and then became a bit more convoluted when multiple windows need to get the same information.
Solution:
To solve this, I decided to implement a very simple subscription style connection:
const ChannelSubscribeAction = 'channel-subscribe';
const ChannelUnsubscribeAction = 'channel-unsubscribe';
const ErrorDataChannel = 'error-data';
// handle channel subscriptions
const channelWindowMap = new Map();
ipcMain.on(ChannelSubscribeAction, (event, channel) => {
if (!channelWindowMap.has(channel)){
channelWindowMap.set(channel, new Set());
ipcMain.on(channel, (event, data) => handleChannelEvent(channel, event, data));
}
channelWindowMap.set(channel, channelWindowMap.get(channel).add(event.sender));
});
ipcMain.on(ChannelUnsubscribeAction, (event, channel) => {
if (!channelWindowMap.has(channel)) return;
channelWindowMap.set(channel, channelWindowMap.get(channel).remove(event.sender));
});
function handleChannelEvent(channel, event, data){
if (!channelWindowMap.has(channel)) return;
channelWindowMap.get(channel).forEach((webContentWin) => {
webContentWin.send(channel, data);
// if we get an error, open dev tools for the window that had the error
if (channel == ErrorDataChannel){
event.sender.webContents.openDevTools();
}
});
}
This allows for any window to subscribe to any channel, and then later unsubscribe if desired. In my code here, I also am detecting when script errors occur and triggering the dev tools to open for that specific window to have a closer look.
The channels are all defined in a single simple enum file and then when each window starts up, it calls in:
ipcRenderer.send(ChannelSubscribeAction, Channels.MainChannel);
Note: There may be some vulnerabilities that come with this approach.
No comments:
Post a Comment