I'm writing a CRA + Electron app and I need to use ipcRenderer.invoke for inter-processes communication. I was able to make ipcRenderer.send and ipcRender.on work in contextIsolation mode, but no luck with ipcRender.invoke. For some reason I don't understand, I can't get the handler response back to renderer in any form (promise or value), all I get is "undefined" value.
preload.js
const { contextBridge, ipcRenderer } = require('electron');
// whitelist channels
const validChannels = ["toMain", "fromMain", "invokeMain"]
// Expose protected methods that allow the renderer process to use
// the ipcRenderer without exposing the entire object
contextBridge.exposeInMainWorld(
"apiKey", {
sendApi: (channel, ...args) => {
if (validChannels.includes(channel)) {
ipcRenderer.send(channel, ...args);
}
},
onApi: (channel, func) => {
if (validChannels.includes(channel)) {
// Deliberately strip event in func as it includes `sender`
ipcRenderer.on(channel, (event, ...args) => func(...args));
}
},
invokeApi: (channel, ...args) => {
if ( validChannels.includes(channel) ) {
ipcRenderer.invoke(channel, ...args).then( (value) =>{
console.log('apiKey.invokeApi:', value);
return value;
});
};
},
}
);
main.js
ipcMain.handle('invokeMain', async (event, ...arg) => {
console.log ('invokeMain received arg:', ...arg);
let response = 'pong';
//return new Promise( (resolve) => setTimeout(resolve(response), 2000), (reject) => reject() );
let prom = new Promise( (resolve) => setTimeout(resolve(response), 2000), (reject) => reject() );
let result = await prom;
console.log ('invokeMain response to Renderer:', prom);
return prom;
//return result;
})
Renderer.js
//Invoke Main
let invokeMessage = "ping";
async function send (invokeMessage) {
console.log('ipcMain.handle response:', window.apiKey.invokeApi('invokeMain', invokeMessage));
// let response = await window.apiKey.invokeApi('invokeMain', invokeMessage)
// console.log('ipcMain.handle response:', response);
// response.then((value) =>{
// console.log('ipcMain.handle response:', value);
// });
};
send(invokeMessage);
Can anybody point me what I'm doing wrong please ? thanks in advance
I got it working by returning the promise of the invoke method from the preload instead of the value.
In my preload:
And handle it directly in the renderer :