If you struggled as well with "bubbling" exceptions between IpcMain and IpcRenderer in electron.js here is a self-exploratory, and simple solution that I created to solve this issue:
import {ipcMain, IpcMainInvokeEvent, ipcRenderer} from 'electron';
export interface channelMessage<T> {
message?: T;
error?: any;
}
export function handleMessageFromRenderer<T>(channel: string, listener: (event: IpcMainInvokeEvent, ...args: any[]) => Promise<void> | any) {
ipcMain.handle(channel, async (event, args) => {
const response: channelMessage<T> = {};
try {
response.message = await listener(event, args);
} catch (e) {
response.error = e;
}
return response;
});
}
export async function sendMessageToMain(channel: string, ...args: any[]): Promise<any> {
const {message, error} = await ipcRenderer.invoke(channel, ...args);
if (error) {
throw error;
}
return message;
}
now instead of passing a message using ipcRenderer.invoke
and icpMain.handle
you can just use sendMessageToMain
and sendMessageToMain
as in the following example:
xport const settingChannels = {
openLogFile: 'open-log-file',
updateApplication: 'update-application',
};
export const settingsApi = {
openLogFile: async () => {
await sendMessageToMain(settingChannels.openLogFile);
},
updateApplication: async (version) => {
await sendMessageToMain(settingChannels.updateApplication, {version});
},
};
export function registerSettingsApi() {
log.debug('registering settings apis');
handleMessageFromRenderer(settingChannels.openLogFile, async (event): Promise<void> => {
log.trace('handling open log');
await settingsHandler.openLogFile();
});
handleMessageFromRenderer(settingChannels.updateApplication, async (event, args): Promise<void> => {
log.trace('handling start app update');
await settingsHandler.updateApplication(args.version);
});
}
Top comments (0)