Я разрабатываю приложение, используя Electron и vue.
Я использую это решение для связи между main и renderer, поэтому у меня есть три файла preload.js
: main и renderer.
// preload.js
const { contextBridge, ipcRenderer } = require("electron");
contextBridge.exposeInMainWorld("api", {
send: (channel, data) => {
// whitelist channels
let validChannels = ["msgbox", "loadall", "savekv", "saveall"];
if (validChannels.includes(channel)) {
ipcRenderer.send(channel, data);
}
}
});
// main
const { ipcMain, dialog } = require('electron')
ipcMain.on("msgbox", (event, args) => dialog.showMessageBox({ message: args }))
ipcMain.on("saveall", (event, config) => dialog.showMessageBox({ message: config }))
// renderer
test() {
window.api.send("saveall", "hahaha"); // <- does not work
window.api.send("msgbox", "haha"); // <- work
}
Однако в файле рендеринга window.api.send("msgbox", "haha");
работает, а window.api.send("saveall", "hahaha");
нет.
Версия Electron 13.6.6 macOS Monterey 12.1
Решение проблемы
Теоретически нет причин, по которым оба диалоговых окна не должны отображаться одновременно ( hahaha
тогда haha
).
На самом деле я заметил, что в 50% случаев только одно из двух диалоговых окон будет отображаться при первоначальном нажатии на файл button
. Выбор диалогового окна был случайным, когда отображалось только одно. Я подозреваю, что это может иметь какое-то отношение к внутренней работе Javascript стека и цикла событий.
Чтобы оба диалоговых окна отображались все время, задержка отображения второго диалогового окна всего на 10 мс будет работать в 100% случаев. Кроме того, порядок диалоговых окон всегда будет гарантирован. ИИ: hahaha
тогда haha
.
Приведенные выше результаты были протестированы как на Electron v13.6.6, так и на Electron v18.1.0 (Windows 10) с приведенным ниже кодом.
preload.js
(основной процесс)
const contextBridge = require('electron').contextBridge;
const ipcRenderer = require('electron').ipcRenderer;
contextBridge.exposeInMainWorld(
'api', {
send: (channel, args) => {
let validChannels = ["msgbox", "loadall", "savekv", "saveall"];
if (validChannels.includes(channel)) {
ipcRenderer.send(channel, args);
}
}
}
);
main.js
(основной процесс)
const electronApp = require('electron').app;
const electronBrowserWindow = require('electron').BrowserWindow;
const electronDialog = require('electron').dialog;
const electronIpcMain = require('electron').ipcMain;
const nodePath = require('path');
let window;
function createWindow() {
const window = new electronBrowserWindow({
x: 0,
y: 0,
width: 800,
height: 600,
show: false,
webPreferences: {
nodeIntegration: false,
contextIsolation: true,
preload: nodePath.join(__dirname, 'preload.js')
}
});
window.loadFile('index.html')
.then(() => { window.show(); });
return window;
}
electronApp.on('ready', () => {
window = createWindow();
});
electronApp.on('window-all-closed', () => {
if (process.platform!== 'darwin') {
electronApp.quit();
}
});
electronApp.on('activate', () => {
if (electronBrowserWindow.getAllWindows().length === 0) {
createWindow();
}
});
// ---
electronIpcMain.on('msgbox', (event, args) => {
console.log(args); // Testing
electronDialog.showMessageBox({message: args} )
});
electronIpcMain.on('saveall', (event, config) => {
console.log(config); // Testing
electronDialog.showMessageBox({message: config} )
});
index.html
(процесс рендеринга)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Electron Test</title>
</head>
<body>
<input type="button" id="button" value="button">
</body>
<script>
document.getElementeById('button').addEventListener('click', () => {
// Test 1 - Inconsistent results
window.api.send("saveall", "hahaha");
window.api.send("msgbox", "haha");
// Test 2 - Consistent results
// window.api.send("saveall", "hahaha");
// setTimeout(() => { window.api.send("msgbox", "haha"); }, 10);
});
</script>
</html>
Комментариев нет:
Отправить комментарий