Comunicación entre procesos (IPC) en ElectronJS

ElectronJS se utiliza para crear aplicaciones de escritorio nativas multiplataforma utilizando tecnologías web como HTML , CSS y JavaScript que pueden ejecutarse en los sistemas operativos Windows, macOS y Linux. Combina el motor Chromium y NodeJS en un solo tiempo de ejecución. Varios proyectos notables de código abierto como Visual Studio Code, Slack, Atom, Postman y Brave Browser se desarrollan utilizando Electron.
El electrón se puede clasificar en dos procesos principales: –  

  • Proceso principal
  • Proceso de renderizado

IPC en Electron: un solo proceso principal puede tener múltiples procesos de representación. Cada proceso de renderizado se puede considerar como una nueva pestaña en el navegador. En este tutorial, discutiremos cómo Electron se comunica entre estos procesos usando Inter-Process Communication (IPC) . Electron nos proporciona dos módulos IPC para ayudar a la comunicación entre los procesos,

  • ipcMain: Este Módulo se utiliza para comunicarse desde el Proceso Principal a los Procesos Renderizadores. Se define y utiliza en el Proceso Principal. Maneja todos los mensajes sincrónicos y asincrónicos que se envían desde el proceso del renderizador.
  • ipcRenderer: Este Módulo se utiliza para comunicar desde los Procesos Renderer al Proceso Principal. Se define y utiliza en los Procesos Renderer. Proporciona la capacidad de enviar y recibir mensajes del proceso principal, de forma sincrónica y asincrónica.

Se recomienda enfáticamente no realizar cálculos pesados ​​en los Procesos de representación para evitar que la aplicación disminuya su rendimiento y consuma más recursos. En cambio, deberíamos usar IPC para distribuir estas tareas al Proceso principal y dejar que el Proceso principal maneje cualquier cálculo pesado en la aplicación. Hay tres diferencias principales entre la transferencia de datos síncrona y la transferencia de datos asíncrona en IPC,  

  1. El método ipc.send() se usa para la transferencia de datos asíncrona, mientras que para la transferencia de datos síncrona se usa el método ipc.sendSync() en su lugar.
  2. Necesitamos implementar específicamente una función de devolución de llamada para manejar la respuesta proveniente del proceso principal en la transferencia de datos asíncrona. En el caso de la transferencia de datos síncrona, no necesitamos implementar la función de devolución de llamada ya que el método ipc.sendSync() devolverá los datos.
  3. En el proceso principal ( archivo main.js ), el método win.webContents.send() se utiliza para la transferencia de datos asíncrona. Esto se puede reemplazar con el método event.returnValue() para la transferencia de datos síncrona.

Nota: este tutorial también asume que está familiarizado con los requisitos previos que se tratan en el enlace mencionado anteriormente.
Estructura del proyecto: Comencemos con los componentes básicos del Tutorial, 

npm init
  • Siga los pasos dados para generar el archivo package.json

  • Paso 3: asegúrese de que Electron esté instalado; de lo contrario, instálelo ahora. 
     
  • Paso 4: cree un archivo main.js de acuerdo con la estructura del proyecto. Este archivo es el Proceso Principal y actúa como un punto de entrada a la aplicación. 
     

javascript

const { app, BrowserWindow } = require('electron')
let win;
 
function createWindow() {
  // Create the browser window.
  win = new BrowserWindow({
    width: 800,
    height: 600,
    webPreferences: {
      nodeIntegration: true
    }
  })
 
  // and load the index.html of the app.
  win.loadFile('src/index.html')
 
  // Open the DevTools.
  // win.webContents.openDevTools()
 
  //Quit app when main BrowserWindow Instance is closed
  win.on('closed', function () {
    app.quit();
  });
}
 
// This method will be called when the Electron has finished
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs.
app.whenReady().then(createWindow)
 
// Quit when all windows are closed.
app.on('window-all-closed', () => {
  // On macOS it is common for applications and their menu bar
  // to stay active until the user quits explicitly with Cmd + Q
  if (process.platform !== 'darwin') {
    app.quit()
  }
})
 
app.on('activate', () => {
  // On macOS it's common to re-create a window in the app when the
  // dock icon is clicked and there are no other windows open.
  if (BrowserWindow.getAllWindows().length === 0) {
    createWindow()
  }
})
  • Paso 5: Cree el archivo index.html dentro del directorio src . El index.html se procesa en su proceso individual mediante el archivo main.js en el inicio de la aplicación. Cada Renderer Process también puede tener su propio archivo CSS y JavaScript asociado. 
    En index.html

html

<!DOCTYPE html>
<html>
 
<head>
    <meta charset="UTF-8">
    <title>Hello World!</title>
   
    <!-- https://electronjs.org/docs/tutorial/security#csp-meta-tag -->
    <meta http-equiv="Content-Security-Policy"
          content="script-src 'self' 'unsafe-inline';" />
</head>
 
<body>
    <h1>Hello Geeks!</h1>
    <div>
        We are using node
        <script>
            document.write(process.versions.node)
        </script>, Chrome
        <script>
            document.write(process.versions.chrome)
        </script>, and Electron
        <script>
            document.write(process.versions.electron)
        </script>.
    </div>
    <script src="index.js"></script>
</body>
 
</html>
  • Paso 6: para iniciar la aplicación Electron, ejecute el comando, siendo «inicio» el script que hemos definido en el archivo package.json .
npm start
  • Producción:

Transferencia de datos asíncrona: dado que hemos configurado la aplicación electrónica básica, definamos una nueva instancia de BrowserWindow que representará una nueva página web. Esta nueva página web será el archivo new-window.html . Luego implementaremos IPC asíncrono para comunicar datos entre el archivo new-window.html y el archivo index.html .

  • nueva-ventana.html:

html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>New Window</title>
    <meta http-equiv="Content-Security-Policy"
          content="script-src 'self' 'unsafe-inline';" />
</head>
<body>
    <div>New Window Opened !</div>
     
    <br>
    <input type="text">
    <button id="submit">Pass Value to Main Window</button>
 
    <script src="new-window.js"></script>
</body>
</html>
  • index.html: a partir de ahora, esta página web no se llama desde ningún lugar dentro de la aplicación. Para cambiar esto, inserte el siguiente código en el archivo  index.html justo encima de la etiqueta del script.
     

html

<h3>Aynschronous Message Sending</h3>
<div>
    Value Received From Renderer Process -
  <span id="value"></span>
</div>
<br>
<button id="new">
  Click Me to Open New Window
</button>
  • índice.js:

javascript

const electron = require('electron')
const path = require('path')
// BrowserWindow Instance is a part of the Main Process,
// To fetch its instance from the Main Process,
// Use electron.remote
const BrowserWindow = electron.remote.BrowserWindow
 
var update = document.getElementById('value');
var button = document.getElementById('new');
 
button.addEventListener('click', function (event) {
    // Linking to new-window.html
    const newPath = path.join('file://', __dirname, 'new-window.html');
    let win = new BrowserWindow({
        // To display the Default Frame of the Window
        // consisting of default Menu
        frame: true,
         
        // Makes the Renderer Window Sticky,
        // Will always stay on top despite focus change
        alwaysOnTop: true,
        width: 600,
        height: 400,
        webPreferences: {
            nodeIntegration: true
        }
    });
 
   // Destroy the BrowserWindow Instance on close
    win.on('close', function () {
        win = null;
    });
 
    // win.webContents.openDevTools();
    win.loadURL(newPath);
    win.show();
});
  • Salida: Con esto nuestra GUI está lista. Al iniciar la aplicación.

Para pasar los datos de la etiqueta de «entrada» en new-window.html a index.html usando Asynchronous IPC, realice los siguientes pasos: 

  • Paso 1: en el archivo new-window.js ,

javascript

const electron = require('electron')
const remote = electron.remote;
// Import the ipcRenderer Module from Electron
const ipc = electron.ipcRenderer;
 
var input = document.querySelector('input');
var submit = document.getElementById('submit');
 
// Adding Click EventListener to the Button
submit.addEventListener('click', function () {
    console.log(input.value);
 
    // Calling the ipcRenderer.send()
    // To send the value from the input tag with
    // a Unique Key to the main process
    // Asynchronously
    ipc.send('update-value', input.value);
    remote.getCurrentWindow().close();
});
  • Paso 2: en el archivo main.js , importe el módulo ipcMain de electron.
const ipcMain = require('electron').ipcMain
  • Agregue lo siguiente al final del archivo,

javascript

// Responsible for Communication of data from Main
// process to the Renderer Process
// Received the value send from the new-window.js file
// Identifies the data passed based on the Key
// Which was set in the ipc.send() method in new-window.js file  
ipcMain.on('update-value', function (event, arg) {
  console.log(arg);
   
  // Passing the data from Main Process to index.html
  // BrowserWindow Instance, value will be received in
  // the index.js based on the Key set here. Using the
  // 'win.webContents.send' method for Asynchronous Data Transfer
  win.webContents.send('updateValue', arg);
});
  • Paso 3: en el archivo index.js , importe el módulo ipcRenderer de electron
const ipc = electron.ipcRenderer;
  • Agregue lo siguiente al final del archivo,

javascript

// Using the ipcRenderer.on() method
// Implementing the Callback Function for Asynchronous IPC,
// To receive the data based on the key set in the main.js file
ipc.on('updateValue', function(event, arg) {
    console.log(arg);
     
    // Updating the value of the HTML Tag with the Data Received
    // In Case the Data Received is not a Number and is
    // some arbitrary Value,display will show as NaN (Not a Number)
    update.innerHTML = Number(arg);
});
  • Salida: Hemos implementado con éxito IPC asíncrono.

Transferencia de datos síncrona: ahora implementaremos IPC síncrono entre el proceso principal y el proceso de representación y visualizaremos las diferencias entre ellos como se explicó anteriormente.

  • Paso 1: en el archivo index.html , agregue el siguiente código justo después de la etiqueta del botón y antes de la etiqueta del script .

html

<br>
<h3>Synchronous Message Sending</h3>
<div>Value Received From Main Process -
  <span id="received"></span>
</div>
<br>
<button id="send">
  Click Me for Synchronous Message
</button>
  • Paso 2: El botón ‘Haz clic en mí para recibir un mensaje síncrono’ no tiene ninguna funcionalidad asociada. Agregaremos EventListener al botón agregando el siguiente código en el archivo index.js .

javascript

var received = document.getElementById('received')
var button2 = document.getElementById('send');
 
// Adding Click EventListener to button2
// For Synchronous Message Transfer we are using the 'ipc.sendSync' method
// We do not need to Implemented any Callbacks to handle the Response
// The 'ipc.sendSync' method will return the data from the Main Process
button2.addEventListener('click', function(event) {
 
    // Setting the Key and the Message to be sent to the Main Process
    const data = ipc.sendSync('synchronous', 'Message to Main Window');
 
    // Setting the Data received to the <span> tag
    received.innerHTML = data;
});
  • Paso 3: en el archivo main.js , agregue el siguiente código al final del archivo,

javascript

ipcMain.on('synchronous', (event, arg) => {
 
  // Using this method instead of 'win.webContents.send'
  // for Synchronous Message Transfer
  // The Value of arg = 'Message to Main Window'
  // In case we do not use 'event.returnValue', We will
  // get the following Error
  // 'Uncaught Error: Unable to deserialize cloned data due to
  // invalid or unsupported version.'
  event.returnValue = 'Synchronous Message Sent';
});
  • Producción:

Publicación traducida automáticamente

Artículo escrito por radheshkhanna y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *