Comunicación entre procesos en Electron.js
Índice de contenido
Una vez que ya superamos la guía para crear tu primera aplicación en Electron. Hay muchos escenarios en los cuales necesitamos comunicar ambos procesos, que al ocurrir un suceso en el proceso principal y/o el proceso de renderizado poder enviar dicho mensaje en cualquier momento para realizar alguna acción determinada; poder enviar mensajes mediante eventos entre procesos es particularmente útil para realizar operaciones que solamente puedan ejecutarse en alguno de los lados pero que necesitamos comunicar al otro lado; por ejemplo:
- Si deseamos abrir una nueva ventana al dar un click sobre un botón, en donde el botón obviamente está en la página web, es lógico que desde la página web, debemos de enviar un mensaje al proceso principal para abrir dicha ventana.
- Si desde el componente principal debemos de pasar datos a la página web que van a ser tomados como referencia para construir la interfaz de la aplicación; estos datos, pueden ser suministrados en cualquier comento, ya sea, cuando carga la página web, al interactuar el usuario con la aplicación, etc.
En resumen, como cualquier otro paradigma, por ejemplo el basado en el cliente y servidor usado por las aplicaciones web, es imprescindible comunicar las capas o procesos que se encuentren involucrados, ya sea de manera directa o indirecta y vamos a conocer en detalle cómo realizar estos procesos.
En Electron, contamos con un solo proceso principal y uno o más procesos de renderizados o páginas web; la comunicación entre ambos, se hacen mediante un par de módulos:
- ipcMain: Este módulo se utiliza para comunicarse desde el proceso principal a los procesos de renderizado.
- ipcRenderer: este módulo se utiliza para comunicarse desde los procesos de renderizado al proceso principal.
Analicemos en la práctica cada uno de ellos.
Proceso principal a proceso de renderizado
Para poder enviar un mensaje a la página web desde el proceso principal, tenemos la siguiente función:
<window>.webContents.send(<EVENT>,<VALUE>)Desde el cliente nos tenemos que suscribir a un evento; necesitamos importar un objeto ipcRenderer desde Electron y escuchar el canal establecido.
const { ipcRenderer } = require('electron')
ipcRenderer.on(<EVENT>, (event, arg) => {
// TO DO
});Proceso de renderizado a proceso principal
Para poder enviar mensaje desde el proceso de renderizado o página web, lo tenemos muy sencillo, basta con pasar desde la página web el mensaje:
const { ipcRenderer } = require('electron')
ipcRenderer.send('message', <DATA>)Desde el proceso principal, tenemos un evento callback:
const {ipcMain} = require('electron')
ipcMain.on('message',(event, arg) => {
// TO DO
})Inicializar listados entre el proceso principal y el proceso de renderizado en Electron JS
Para pasar los datos definidos en el proceso principal, vamos a utilizar la siguiente estructura; los datos, van a estar disponibles desde el proceso principal, para simular una estructura externa como una base de datos, vamos a crear un archivo aparte al index.js que es el que se encargará de suministrar los datos, crearemos un par de módulos con los datos para que sean fácilmente consumibles:
data.js
const contacts = [
{
'name': 'Alex Alexis',
'image': 'https://randomuser.me/api/portraits/women/56.jpg',
'last_chat': [
{
'date': '9:15 AM',
'message': 'Lorem ipsum dolor sit amet',
}
]
},
{
'name': 'Eli Barrett',
'image': 'https://randomuser.me/api/portraits/women/96.jpg',
'last_chat': [
{
'date': '8:30 PM',
'message': 'Lorem ipsum dolor sit amet',
}
]
},
{
'name': 'Kylie Young',
'image': 'https://randomuser.me/api/portraits/women/45.jpg',
'last_chat': [
{
'date': '8:30 PM',
'message': 'Lorem ipsum dolor sit amet',
}
]
},
{
'name': 'Kylie Young',
'image': 'https://randomuser.me/api/portraits/women/45.jpg',
'last_chat': [
{
'date': '8:30 PM',
'message': 'Lorem ipsum dolor sit amet',
}
]
}
]
const chats = [
{
'user': {
'name': 'Alex Alexis',
'image': 'https://randomuser.me/api/portraits/women/56.jpg',
},
'chat':
{
'date': '9:15 AM',
'message': 'Lorem ipsum dolor sit amet consectetur adipisicing elit. Doloribus reprehenderit voluptatibus cumque, deserunt deleniti consequatur adipisci nisi consequuntur sunt itaque? Sunt aspernatur, ratione labore ipsam enim unde itaque dolorum magni?',
}
},
{
'user': {
'name': 'Eli Barrett',
'image': 'https://randomuser.me/api/portraits/women/58.jpg',
},
'chat':
{
'date': '9:50 AM',
'message': 'Lorem ipsum dolor sit amet consectetur adipisicing elit. Doloribus reprehenderit voluptatibus cumque, deserunt deleniti consequatur adipisci nisi consequuntur sunt itaque? Sunt aspernatur, ratione labore ipsam enim unde itaque dolorum magni?',
}
},
]
module.exports.contacts = contacts;
module.exports.chats = chats;Desde el index, activamos la integración con Node y los consumimos; definimos un evento en el cual, al cargar la ventana (página web) mediante el evento de did-finish-load, transmitimos los datos vía un mensaje:
index.js
const { chats, contacts } = require('./data')
***
function createWindow(){
let win = new BrowserWindow({
width: 1300,
height:900,
webPreferences:{
nodeIntegration: true,
contextIsolation: false
}
})
win.loadFile("index.html")
win.webContents.openDevTools()
win.webContents.on('did-finish-load', () => {
win.webContents.send('pr-chats',chats)
win.webContents.send('pr-contacts',contacts)
});
}Desde la página web, gracias a que activamos la integración con Node, podemos importar el módulo de ipcRenderer, para poder comunicarnos con el proceso principal, específicamente, nos interesa crear un escuchador (listener) para recibir los datos enviados desde el proceso principal:
index.html
<script>
const { ipcRenderer } = require('electron')
function createContacts(contacts) {
var lis = ''
contacts.forEach((c) => {
lis += `<li class="p-2 card mt-2">
<div class="card-body">
<div class="d-flex">
<div>
<img class="rounded-pill me-3" width="60"
src="${c.image}">
</div>
<div>
<p class="fw-bold mb-0 text-light">${c.name}</p>
<p class="small text-muted">${c.last_chat[0]['message']}</p>
</div>
<div>
<p class="small text-muted">${c.last_chat[0]['date']}</p>
<span class="badge bg-danger rounded-pill float-end">1</span>
</div>
</div>
</div>
</li>`
})
document.querySelector('.contact').innerHTML = lis;
}
function createChats(chats) {
var lis = ''
chats.forEach((c) => {
lis += ` <div class="d-flex chat">
<div class="w-75 ">
<div class="card bg-dark">
<div class="card-body text-light">
${c.chat.message}
</div>
</div>
<p class="small text-muted float-end">${c.chat.date}</p>
</div>
<div class="w-25 d-flex align-items-end">
<img class="rounded-pill ms-3 avatar" src="${c.user.image}"/>
</div>
</div>`
})
document.querySelector('.chats').innerHTML = lis;
}
ipcRenderer.on('pr-chats',(event, chats)=>{
createChats(chats)
})
ipcRenderer.on('pr-contacts',(event, contacts)=>{
createContacts(contacts)
})
</script>Siguiente paso, conoce como Activar la consola de desarrolladores en Chrome (Debug).
Acepto recibir anuncios de interes sobre este Blog.
Poder enviar mensajes mediante eventos entre procesos es útil para realizar operaciones que solamente puedan ejecutarse en alguno de los lados pero que necesitamos comunicarse.