I wrote a special article referring to the electron Chinese official website and adding my own understanding. If you feel like it, please give a thumbs up or follow it. Please leave a comment and point out question A on wechat public account: [Daily Life of Cat 12]

Electron communication

- Use 'ipcMain' and 'ipcRenderer' modules - use the electron. Remote moduleCopy the code

We will now focus on the first method of communication

Understand the main and renderer processes

Main Process

  • A electron can only have one main process
  • The main process means that after you run the electron. Command, the specified file in main under the package.json file in the corresponding current directory will be executed

- The interface associated with creating a GUI(similar to creating a window) can only be called through the main process.Copy the code

Renderer Process

  • Pages created by the main process calling the GUI interface have their own process, called the renderer. The main process instantiates BrowserWindow. Each BrowserWindow instance renders a Web page, independently of each other. When a BrowserWindow is destroyed, the corresponding rendering process is terminated.
  • Renderers are managed by the main process, each independent of the other and managing only their own Web pages

If they need to communicate, they need to communicate with IPC

The ipc communication

In electron, we need the Main Process and the Renderer Process to communicate, using two modules

  • ipcMain

    Asynchronous communication from the main process to the renderer. IpcMain is an instance of EventEmitter. When used in the main process, it handles asynchronous and synchronous information sent from the renderer process (web page). Messages sent from the renderer process will be sent to this module.

  • ipcRenderer

    Asynchronous communication from the renderer process to the main process. IpcRenderer is an instance of EventEmitter. You can use some of the methods it provides to send synchronous or asynchronous messages from the renderer (web page) to the main process. It can also receive messages returned by the main process.

Relevant methods of IPC communication

The method by which the renderer communicates with the main process

Directory preparation, modification and deletion are all in these few file operations

├─ ├─ ├─ ├─ ├─ ├─ ├─ ├─ index.html // web-pageCopy the code

index.html

<! DOCTYPEhtml>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="Width = device - width, initial - scale = 1.0">
    <title>2020-01-08</title>
</head>

<body>Electron communication demonstration<script src="./renderer.js"></script>// Import js externally</body>

</html>
Copy the code

main.js

const { app, BrowserWindow, ipcMain } = require("electron");
function createWindow() {
  const win = new BrowserWindow({
    width: 1920.height: 1080.webPreferences: {
      nodeIntegration: true.contextIsolation: false,}}); win.webContents.openDevTools();// Open the debugging tool
  win.loadFile("index.html");
}

app.whenReady().then(createWindow);

app.on("window-all-closed".() = > {
  if(process.platform ! = ="darwin") { app.quit(); }}); app.on("activate".() = > {
  if (BrowserWindow.getAllWindows().length === 0) { createWindow(); }}); ipcMain.on("async-message".(event, arg) = > {
  // Asynchronous message reply
  console.log('async-message: I received an asynchronous message', arg);
  event.reply("async-reply"."Dude, I got a message. - It's asynchronous.");
});

ipcMain.on("sync-message".(event, arg) = > {
  // Synchronize message reply
  console.log('async-message: I received a synchronous message', arg);
  event.returnValue = "Dude, I got a message. - From sync.";
});

Copy the code

renderer.js

const { ipcRenderer } = require("electron");
// Synchronize messages
let message = ipcRenderer.sendSync("sync-message"."Send a synchronous message.");
console.log("Synchronize messages :", message);

// Asynchronous messages
ipcRenderer.on("async-reply".(event, arg) = > {
  console.log("Asynchronous message :", arg);
});

ipcRenderer.send("async-message"."Send an asynchronous message.");

Copy the code

package.json

{
  "name": "2020-01-08"."version": "1.0.0"."description": ""."main": "main.js"."scripts": {
    "start": "electron ."
  },
  "keywords": []."author": ""."license": "ISC"."devDependencies": {
    "electron": "^ 11.1.1." "}}Copy the code

The results of

Electron (main process)

Async-message: I received a synchronous message send a synchronous message async-message: I received an asynchronous message send an asynchronous messageCopy the code

Client (renderer)

Synchronous message: dude I got a message - from synchronous asynchronous message: dude I got a message - from asynchronousCopy the code

This section will modify and operate based on these files

For the above content mainly used several methods to achieve the rendering process to the main process communication

Ipcmain. on(Channel, Listener) The main process listens for communication from the renderer. IpcMain is an instance of EventEmitter

  • Channel Specifies the name of the event to listen on, of type String

  • The listener listens to a callback that has two input arguments

    • Event IpcMainEvent Indicates the IPC event

      Event There are two types of messages that need to be replied. One is asynchronous reply and the other is synchronous reply

      • This parameter is required when synchronizing messages are returnedevent.returnValue.
      • event.reply(...)Send an asynchronous message back to the sender
      • Both are shown in the demo above
    • . Args any[] are all input arguments passed by the client

The IpcMainEvent inherited Event has the following attribute values

  • ProcessId (type Integer) The internal ID of the renderer process that sent this message
  • FrameId Integer Type) The ID of the renderer frame from which the message was sent (possibly iframe)
  • ReturnValue (type any)) sets it to the value to be returned in the synchronization message
  • Reply (Function type) the Function that sends an IPC message to the renderer framework, which sends the original message that is currently being processed. You should use the “reply” method to reply to sent messages to ensure that the reply will go to the correct process and framework.
    • channel String
    • . args any[]

**ipcRenderer.sendSync(channel, … Args) ** The renderer sends synchronization messages to the main process

  • Channel Indicates the event name. The value is a String
  • . args any[]

Return any – the value sent by the ipcMain handler.

Sending synchronous messages will block the renderer’s rendering process, similar to async await mode, and it is better to choose the asynchronous version of processing

ipcRenderer.send(channel, … Args), the renderer sends an asynchronous message to the main process

  • Channel Indicates the event name. The value is a String
  • . args any[]

All args parameters above can only be serialized strings, all functions, Promise, Symbol, weakMaps, weakSets will throw exceptions,DOM node in electron9 will also throw exceptions

Other functions

Only listen for one event

ipcMain.once(channel, listener)

  • Channel Specifies the name of the event to listen on, of type String

  • The listener listens to a callback that has two input arguments

    • Event IpcMainEvent Indicates the IPC event

      Event There are two types of messages that need to be replied. One is asynchronous reply and the other is synchronous reply

      • This parameter is required when synchronizing messages are returnedevent.returnValue.
      • event.reply(...)Send an asynchronous message back to the sender
      • Both are shown in the demo above
    • . Args any[] are all input arguments passed by the client

This event function will only listen once and will be removed after listening

Use ipcMain. On listening

# main.js

// Normal listener reply
ipcMain.on("on-message".(event, arg) = > {
  event.reply("on-reply-message", arg);
});

# renderer.js

for (let index = 0; index < 5; index++) {
  ipcRenderer.send("on-message".The first `${index}Time `);
}

ipcRenderer.on("on-reply-message".(event, arg) = > {
  console.log(` reply:${arg}`);
});

/ / the resultResponse: the first0First reply: No1First reply: No2First reply: No3timeCopy the code

Use ipcMain. Once to monitor

# main.js

ipcMain.once("one-message".(event, arg) = > {
  event.reply("one-reply-message", arg);
});

# renderer.js

for (let index = 0; index < 5; index++) {
  ipcRenderer.send("one-message".The first `${index}Time `);
}

ipcRenderer.on("one-reply-message".(event, arg) = > {
  console.log(` reply:${arg}`);
});

/ / the resultResponse: the first0timeCopy the code

ipcRenderer.once(channel, listener)

- The method is similar to on event listeningCopy the code

This method also listens for only one message from the main process and automatically removes the event

# main.js

ipcMain.on("one-message".(event, arg) = > {
  event.reply("one-reply-message", arg);
});

# renderer.js

for (let index = 0; index < 5; index++) {
  ipcRenderer.send("one-message".The first `${index}Time `);
}

ipcRenderer.once("one-reply-message".(event, arg) = > {
  console.log(` reply:${arg}`);
});

/ / the resultResponse: the first0timeCopy the code

Remove listening events

The ipcmain. removeListener(channel, listener) parameter is removed only if it matches the defined listener function

# main.js

function callback(event, arg) {
  event.reply("reply".'The main process returns a message:${arg}`);
}
ipcMain.on("message", callback);
ipcMain.removeListener("message", callback);

# renderer.js

function watcher(event, arg) {
  console.log(arg);
}
ipcRenderer.send("message"."Render process sends message");
ipcRenderer.on("reply", watcher);

/ / the resultCopy the code

ipcMain.removeAllListeners([channel])

- channel removes all listeners of this eventCopy the code
# main.js

function callback(event, arg) {
  event.reply("reply".'The main process returns a message:${arg}`);
}
ipcMain.on("message", callback);
ipcMain.removeAllListeners("message");// The specified event
//ipcMain.removeAllListeners(); // All events are removed

# renderer.js

function watcher(event, arg) {
  console.log(arg);
}
ipcRenderer.send("message"."Render process sends message");
ipcRenderer.on("reply", watcher);

/ / the resultCopy the code

Asynchronous back and forth communication

The main change is to process the returned results like returning promse, so the input parameters are basically the same

Ipcmain. handle(channel, listener) Listener function of the main process

ipcRenderer.invoke(channel, … Args) the message sending function of the renderer process

# main.js

ipcMain.handle("message".async(event, ... args) => {let someMessage = await Promise.resolve("I am an asynchronous message back.");
  return someMessage;
});

# renderer.js

(async() = > {let result = await ipcRenderer.invoke("message");
    console.log(result); }) ();/ / the resultI am asynchronously returning the messageCopy the code

Ipcmain. handleOnce(channel, listener) a single execution

# main.js

ipcMain.handleOnce("message".async(event, ... args) => {let someMessage = await Promise.resolve("I am an asynchronous message back.");
  return someMessage;
});

# renderer.js

(async() = > {let result = await ipcRenderer.invoke("message");
    console.log(result); }) ();/ / the resultI am asynchronously returning the messageCopy the code

** ipcmain.removeHandler (channel)** Removes listener functions

# main.js

ipcMain.handle("message".async(event, ... args) => {let someMessage = await Promise.resolve("I am an asynchronous message back.");
  return someMessage;
});
ipcMain.removeHandler("message"); // Be sure to write remove that event name
# renderer.js

(async() = > {let result = await ipcRenderer.invoke("message");
    console.log(result); }) ();/ / the resultAn errorCopy the code

Use webworkers to pass information

Ipcrenderer. postMessage(channel, message, [Transfer]) this function is similar to webworker in web pages. Baidu has not found its usage in electron. I wrote a set that seems to be able to pass messages according to webwork (to be corrected)

# main.js

ipcMain.on("port".(e, msg) = > {
  const [port] = e.ports;
  console.log(port, msg, e.ports);
  port.postMessage("Send a message to the render process");
});
# renderer.js
const { port1, port2 } = new MessageChannel();
ipcRenderer.postMessage("port", { message: "hello" }, [port2]);
port1.onmessage = (arg) = > {
  console.log(arg.data);
};
/ / the resultSend a message to the rendererCopy the code

We’re basically talking about renderers sending messages to the main process and getting a response, but in practice, we also have each render process communicating with each other, and the main process communicating with one render process

If you think my article is ok, click a like or follow the next, there are wonderful stories waiting for you oh, but also can cloud masturbation cat