AGIORNAMENTO : il codice sembra funzionare correttamente :
ipcRenderer.on()
esiste ma non riceve gli eventi credo che il problema sia in :
let new_ipcRenderer = {};
for(let pro in ipcRenderer){
new_ipcRenderer[pro] =ipcRenderer[pro];
}
devo far in modo che le proprietà vengano copiate ricorsivamente sospeto in qualche prototipo di prototipo che non venga ricopiato come si deve .
nel frattempo segnalo che il seguente codice risolve il probleam anche se è una soluzione che non mi piace affatto :
contextBridge.exposeInMainWorld(
"electron",
{
ipcRenderer: {
...ipcRenderer,
on: (channel, func) =>ipcRenderer.on(channel, (event, args) =>func(null,args))
}
}
);
Muovendo i primi passi con nel programmare in JavaScript usando Electron mi sono imbatturo in un problema che mi ha richiesto un bel pò di gratacapi per essere risolto .
in pratica per comunicare fra il main process ed il rendering process ci sono le ottime libreire di electronjs cioè ipcRenderer e ipcMain il problema sorge lato cliente con contextIsolation = true e tutte le variabili di ambiente settate di default in electronjs .
la soluzione sarebbe passare tutto ipcRenderer usando il preload attraverso contextBridge di electronjs che permette di far passare un ogetto da un ambiente all’altro in fase di precaricamento in questo modo :
const {ipcRenderer, contextBridge } = require('electron');
contextBridge.exposeInMainWorld(
"electron",
{
ipcRenderer: ipcRenderer
}
);
Però se faccio così mi trovo a poter utilizzare la funzione
ipcRenderer.send()
che mi permette di inviare messaggi a ipcMain
ipcRenderer.on()
non ne vuole sapere di funzionare .prototype
, e quindi come si fa ?//questo codice fa in modo che tutte le funzioni prototipo vengano copiate come se fossero funzioni normali
let new_ipcRenderer = {};
for(let pro in ipcRenderer){
new_ipcRenderer[pro] =ipcRenderer[pro];
}
contextBridge.exposeInMainWorld(
"electron",
{
ipcRenderer: new_ipcRenderer
}
);
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <!-- questo tag qui sotto abilita il Content-Security-Policy in breve csp se vi sono problemi nell'acceso alle risorse valutare di rimuoverlo --> <meta http-equiv="Content-Security-Policy" content="script-src 'self';"> <title>Document</title> </head> <body> <button id="ipc_asincrono">ipc asincrono</button> <button id="ipc_sincrono">ipc sincrono</button> <div id="messaggio_ipc">per ora nessun messaggio </div> <script defer src="./js/web_renderer.js"></script> </body> </html>
const { app, BrowserWindow, ipcMain } = require('electron'); const path = require('path'); const createWindow = () => { const win = new BrowserWindow({ width: 800, height: 600, webPreferences: { preload: path.join(__dirname, 'preload.js'), nodeIntegration: false, nodeIntegrationInWorker: false, contextIsolation: true, enableRemoteModule: false, sandbox: true, webSecurity: true } }) win.loadFile('index.html'); win.webContents.openDevTools();// apre la console di debug di chroome } app.whenReady().then(() => { createWindow() }) app.on('window-all-closed', () => { if (process.platform !== 'darwin'){ app.quit() } }) //END FASE DI AVVIO E CREAZIONE DELLE FINESTRA // START gestione mssaggio IPC ipcMain.on('messaggio_asincrono', (event, args) => { console.log(args); event.sender.send('ris_messaggio_asincrono', 'riposta asincrona a messagio asincrono'); }); // ricevuto messagio sincrono ipcMain.on('messaggio_sincrono', (event, args) => { console.log(args); event.returnValue = 'risposta sincrona a mesagio sincrono'; }); // END gestione mssaggio IPC
const {ipcRenderer, contextBridge } = require('electron'); let new_ipcRenderer = {}; console.log(new_ipcRenderer); for(let pro in ipcRenderer){ new_ipcRenderer[pro] = ipcRenderer[pro]; } contextBridge.exposeInMainWorld( "electron", { ipcRenderer: new_ipcRenderer } );
window.addEventListener('load', (event) => { console.log('page is fully loaded'); console.log(window.electron.ipcRenderer); const ipc_asincrono = document.querySelector("#ipc_asincrono"); const ipc_sincrono = document.querySelector("#ipc_sincrono"); const messaggio_ipc = document.querySelector('#messaggio_ipc'); ipc_asincrono.addEventListener('click', (event) => { window.electron.ipcRenderer.send('messaggio_asincrono', "ecco a te un messaggio asincrono") }); // mi metto in ascolta di un eventuale risposta asincrona window.electron.ipcRenderer.on('ris_messaggio_asincrono', (event, args) => { messaggio_ipc.innerHTML = args; }); ipc_sincrono.addEventListener('click', (event) => { let risposta = window.electron.ipcRenderer.sendSync('messaggio_sincrono', "ecco a te un messagio sincrono"); messaggio_ipc.innerHTML = risposta; }); });