Search code examples
javascriptscopeelectronipcarrow-functions

How can I return data from preloaded Electron script?


I have built a function in preload.js that gets a JSON file sent from main.js. renderer.js loads it fine, but I can't seem to give the data to another variable outside of the arrow function.

main.js

mainWindow.webContents.on('did-finish-load', () => {
  fs.readFile('src/project-files/default.json', 'utf-8', (err, data) => {
    if (err) {
      console.log(err);
      return;
    } else {
      console.log("*** Successfully read JSON file");
      mainWindow.webContents.send('load-default-json-file', data);
      console.log("*** Sent JSON data ***")
    }
  })
})

preload.js

const { contextBridge, ipcRenderer } = require('electron');

contextBridge.exposeInMainWorld('electronAPI', {
  loadDefaultJSON: (callback) => ipcRenderer.on('load-default-json-file', (_event, value) => callback(value))
})

renderer.js

var data; // undefined
electronAPI.loadDefaultJSON((json) => {
  data = json;
  console.log(data); // Works fine
  return data;
});
console.log(data); // Undefined, doesn't work

Any ideas on how to escape the data out of the scope of the function?


Solution

  • In this case you should probably use ipcRenderer.sendSync(...) in preload.js and ipcMain.on( ... ) in main.js to get the data. The reason you are getting undefined is because you are trying to log the data before it is received from main.js. I would try modifying your code as follows:

    main.js

    ipcMain.on('load-default-json-file', (event) => {
      fs.readFile('src/project-files/default.json', 'utf-8', (err, data) => {
        if (err) {
          console.log(err)
          return
        } else {
          console.log('*** Successfully read JSON file')
          event.returnValue = data
          console.log('*** Sent JSON data ***')
        }
      })
    })
    

    preload.js

    const { contextBridge, ipcRenderer } = require('electron')
    
    contextBridge.exposeInMainWorld('electronAPI', {
      loadDefaultJSON: () => ipcRenderer.sendSync('load-default-json-file')
    })
    

    renderer.js

    let data = electronAPI.loadDefaultJSON()
    
    console.log(data)
    
    

    However, remember that your app will freeze/wait until the data is received from main.js. Might be negligible but something to be cautious about.