Comunicación entre Procesos en Electron: Guía Práctica de IPC

En el desarrollo de aplicaciones de escritorio con Electron, la arquitectura se divide principalmente en dos contextos aislados: el proceso principal (Main Process) y el proceso de renderizado (Renderer Process). Para que estos dos entornos puedan intercambiar datos de manera segura y eficiente, el framework proporciona el módulo de Comunicación entre Procesos (IPC, por sus siglas en inglés).

Configuración del Proceso Principal

El proceso principle actúa como el núcleo de la aplicación, gestionando el ciclo de vida, las ventanas nativas y las operaciones del sistema. Utilizaremos el módulo ipcMain para escuchar los eventos enviados desde la interfaz de usuario y el método webContents.send para emitir respuestas o notificaciones.

A continuación, se presenta una implementación refactorizada. Se han eliminado dependencias obsoletas (como el módulo remote), actualizado los ciclos de vida con promesas y renombrado los canales de comunicación para seguir un patrón de nomenclatura claro.

const { app, BrowserWindow, ipcMain, globalShortcut } = require('electron');

let applicationWindow = null;

app.whenReady().then(() => {
   applicationWindow = new BrowserWindow({
       width: 1024,
       height: 768,
       webPreferences: {
           // Nota: Configuración habilitada para fines demostrativos. 
           // En entornos de producción, utilice contextIsolation: true y un script preload.
           nodeIntegration: true,
           contextIsolation: false
       }
   });

   applicationWindow.loadFile('interface.html');

   // Emisión de un mensaje asíncrono hacia el renderizador una vez que el DOM esté listo
   applicationWindow.webContents.on('did-finish-load', () => {
       applicationWindow.webContents.send('backend:status-update', 'El núcleo de la aplicación está activo y listo.');
   });

   applicationWindow.on('closed', () => {
       applicationWindow = null; // Liberación de recursos
   });
});

app.on('will-quit', () => {
   globalShortcut.unregisterAll(); // Limpieza de atajos de teclado globales
});

// Suscripción a mensajes asíncronos provenientes del renderizador
ipcMain.on('frontend:submit-data', (event, payload) => {
   console.log(`[Proceso Principal] Datos interceptados: ${payload}`);
   
   // Respuesta dirigida al canal específico del emisor
   event.reply('backend:acknowledge', `Confirmación: El backend procesó "${payload}" correctamente.`);
});

// Manejo de solicitudes síncronas (bloqueantes)
ipcMain.on('frontend:sync-request', (event, payload) => {
   console.log(`[Proceso Principal] Solicitud síncrona recibida: ${payload}`);
   
   // Retorno inmediato de valor al hilo del renderizador
   event.returnValue = `Respuesta síncrona generada para: ${payload}`;
});

Implementación en el Proceso de Renderizado

En la capa de presentación, el módulo ipcRenderer permite a la interfaz enviar solicitudes al backend de Node.js y suscribirse a las actualizaciones del estado. En este ejemplo, se moderniza el código HTML/JS utilizando escuchas de eventos nativas del DOM (addEventListener) en lugar de atributos en línea, mejorando la separación de responsabilidades.


<html lang="es">
<head>
   <meta charset="UTF-8">
   <meta name="viewport" content="width=device-width, initial-scale=1.0">
   <title>Panel de Comunicación IPC</title>
</head>
<body>
   <h2>Consola de Mensajería</h2>
   <input type="text" id="dataInput" placeholder="Ingrese un mensaje...">
   <button id="btnAsync">Emitir Evento Asíncrono</button>
   <button id="btnSync">Emitir Evento Síncrono</button>

   <script>
       const { ipcRenderer } = require('electron');

       // Escucha de notificaciones de estado del backend
       ipcRenderer.on('backend:status-update', (event, statusMessage) => {
           console.log(`[Renderizador] Notificación del sistema: ${statusMessage}`);
       });

       // Escucha de confirmaciones asíncronas
       ipcRenderer.on('backend:acknowledge', (event, responsePayload) => {
           alert(responsePayload);
       });

       // Lógica para el flujo de comunicación asíncrono
       document.getElementById('btnAsync').addEventListener('click', () => {
           const inputValue = document.getElementById('dataInput').value;
           if (inputValue.trim() !== '') {
               ipcRenderer.send('frontend:submit-data', inputValue);
           }
       });

       // Lógica para el flujo de comunicación síncrono
       document.getElementById('btnSync').addEventListener('click', () => {
           const inputValue = document.getElementById('dataInput').value;
           if (inputValue.trim() !== '') {
               const syncResult = ipcRenderer.sendSync('frontend:sync-request', inputValue);
               console.log('Resultado síncrono inmediato:', syncResult);
               alert(syncResult);
           }
       });
   </script>
</body>
</html>

Etiquetas: Electron ipcMain ipcRenderer Node.js JavaScript

Publicado el 6-16 16:50