title: How to pass ipcRenderer.invoke handler answer to electron renderer process using preload.js
body: <p>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 &quot;undefined&quot; value.</p>
  <p>preload.js</p>
  <pre class="lang-js prettyprint-override"><code>const { contextBridge, ipcRenderer } = require('electron');
  
   // whitelist channels
  const validChannels = [&quot;toMain&quot;, &quot;fromMain&quot;, &quot;invokeMain&quot;]
  // Expose protected methods that allow the renderer process to use
  // the ipcRenderer without exposing the entire object
  contextBridge.exposeInMainWorld(
      &quot;apiKey&quot;, {
          sendApi: (channel, ...args) =&gt; {
              if (validChannels.includes(channel)) {
                  ipcRenderer.send(channel, ...args);
              }
          },
          onApi: (channel, func) =&gt; {
              if (validChannels.includes(channel)) {
                  // Deliberately strip event in func as it includes `sender` 
                  ipcRenderer.on(channel, (event, ...args) =&gt; func(...args));
              }
          },
          invokeApi: (channel, ...args) =&gt; {
              if ( validChannels.includes(channel) ) {
                  ipcRenderer.invoke(channel, ...args).then( (value) =&gt;{
                      console.log('apiKey.invokeApi:', value);
                      return value;
                  });
              };
          },
      }
  );
  </code></pre>
  <p>main.js</p>
  <pre class="lang-js prettyprint-override"><code>ipcMain.handle('invokeMain', async (event, ...arg) =&gt; {
    console.log ('invokeMain received arg:', ...arg);
    let response = 'pong';  
    //return new Promise( (resolve) =&gt; setTimeout(resolve(response), 2000), (reject) =&gt; reject() );
    let prom = new Promise( (resolve) =&gt; setTimeout(resolve(response), 2000), (reject) =&gt; reject() );
    let result = await prom;
    console.log ('invokeMain response to Renderer:', prom);
    return prom;
  //return result;  
  })
  </code></pre>
  <p><a href="https://i.stack.imgur.com/vwvig.png" rel="nofollow noreferrer">Main.js output</a></p>
  <p>Renderer.js</p>
  <pre class="lang-js prettyprint-override"><code>//Invoke Main
  let invokeMessage = &quot;ping&quot;;
  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) =&gt;{
  //        console.log('ipcMain.handle response:', value);
  //    });
  };
  send(invokeMessage);
  </code></pre>
  <p><a href="https://i.stack.imgur.com/6RuT0.png" rel="nofollow noreferrer">Renderer.js output</a></p>
  <p>Can anybody point me what I'm doing wrong please ? thanks in advance</p>