2

In my Electron project, I'm trying to make a module singleton by setting it as a global. Since I use jquery in this module, I import it in the renderer process and then send it to the main via ipc and set it as global there. Here is related part of my code:

main.js:

ipcMain.on( "setGlobal", ( event, global_var) => {
  global[global_var[0]] = global_var[1];
  console.log(global_var);
  event.returnValue = 1;
} );

renderer.js:

const favourites = require("./components/favourites");

console.log(favourites);

ipcRenderer.sendSync("setGlobal", ["favourites", favourites]);

console.log(remote.getGlobal("favourites"));

The outputs of console.logs in the renderer process are in the image below:

renderer output

And the output of the main process is:

[ 'favourites', { favourites: [] } ]

As you see, the object (module) I sent from the ipcRenderer is changed in the ipcMain, it lost its add and init functions. Do you have any idea what is the reason of this behavior and how to fix it?

PS: To be sure, I tested it with a simple objects that contains functions instead of require("favourites"). They are also behaving in the same way. I did a workaround by using only the entities as global and passing them to all of the functions as arguments. However, it's not a good way in sense of code readability.

Bünyamin Sarıgül
  • 3,031
  • 4
  • 30
  • 55

2 Answers2

4

You cannot use IPC like that. As noted in docs (eg. sendSync)

Send a message to the main process synchronously via channel, you can also send arbitrary arguments. Arguments will be serialized in JSON internally and hence no functions or prototype chain will be included.

Your functions are simply not making it to main process.


For making a module singleton you should just use the singleton pattern in your module, and use require in main process and remote.require in renderer. Since require using cache (at least by default), the same module should be returned. (more or less. Further reading can be found here)

For example if you export a class:

let _instance = null
class MyClass {
  constructor() {
    if (_instance === null) _instance = this
    return _instance
  }
  ...
}
module.exports = MyClass
pergy
  • 5,285
  • 1
  • 22
  • 36
  • Thanks for your informative answer! The only problem is that I can't import my module into the main process because it requires `jQuery` and importing it produces error. Thus, I should import it in the renderer. – Bünyamin Sarıgül Jan 17 '19 at 13:31
-1

After @pergy's answer, I decided to drop IPC and use only the globals. So, here is the workaround I find:

main process:

global.provider = {};

renderer process:

const favourites = require("./components/favourites");
remote.getGlobal("provider").favourites = favourites;

other modules:

const favourites = remote.getGlobal("provider").favourites;
Bünyamin Sarıgül
  • 3,031
  • 4
  • 30
  • 55