Electron:等待来自渲染器进程的消息



场景:

我有一个Electron应用程序。我还有一个主进程和一个渲染器进程(这是一个React组件)。主要流程有许多问题。主进程将这些问题一次一个地发送给渲染器进程。一旦呈现器进程接收到问题,它就会将其显示给用户,用户需要回答该问题并点击提交。一旦点击提交,答案就会被发送回主进程进行进一步处理,然后主进程发送下一个问题,以此类推,直到所有问题都得到回答。

当前状态:

我可以将问题发送到渲染器,但我不知道如何等待答案。

说明该想法的代码:

Main:

// Get all questions
const questions = [...];
// Iterate through questions
for (const question of questions) {
// Send question
window.getAllWindows()[0].webContents.send('question', { question: question });
// TODO: Wait for answer
// TODO: do something with answer
}

注意:在回答完所有问题之前,程序无法继续

我知道JavaScript是单线程的,不能阻止代码的执行,这就是为什么我很难实现这一点。

您真正想要的是类似于ipcRenderer.invoke的Electron方法,而不是";渲染到主体和背面再次";,你想要";main进行渲染并再次返回";。

没有真正的";等待";除非您开始使用promise和while或CCD_ 3环路。

与其反复讨论这样的问题,不如将收到的答案数量与总数进行比较问题数量。当收到所有问题/答案后,继续您的下一步应用


main.js(主过程)

'use strict';
const electronApp = require('electron').app;
const electronBrowserWindow = require('electron').BrowserWindow;
const electronIpcMain = require('electron').ipcMain;
const nodePath = require('path');
// Prevent garbage collection
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();
askQuestion(); // <--- Ask first question upon window creation
});
electronApp.on('window-all-closed', () => {
if (process.platform !== 'darwin') {
electronApp.quit();
}
});
electronApp.on('activate', () => {
if (electronBrowserWindow.getAllWindows().length === 0) {
createWindow();
}
});
// ---
const questions = [
{'question': 'Question 1'},
{'question': 'Question 2'},
{'question': 'Question 3'}
]
let answers = [];
electronIpcMain.on('submitAnswer', (event, answer) => {
// Process answer.
answers.push(answer);
if (answers.length < questions.length) {
askQuestion();
} else {
console.log('All questions answered');
console.log(answers);
}
})
function askQuestion() {
window.webContents.send('askQuestion', questions[answers.length].question);
}

preload.js(主过程)

const contextBridge = require('electron').contextBridge;
const ipcRenderer = require('electron').ipcRenderer;
contextBridge.exposeInMainWorld(
'electronAPI', {
// From main to render
askQuestion: (question) => {
ipcRenderer.on('askQuestion', question)
},
// From render to main
submitAnswer: (answer) => {
ipcRenderer.send('submitAnswer', answer)
}
});

index.html(主过程)

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Electron Test</title>
<meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline';"/>
</head>
<body>
<div>
<h2>Question</h2>
<div id="question"></div>
</div>
<div>
<h2>Answer</h2>
<textarea id="answer" rows="8" cols="50"></textarea>
</div>
<input type="button" id="submit" value="Submit">
</body>
<script>
let questionField = document.getElementById('question');
let answerField = document.getElementById('answer');
window.electronAPI.askQuestion((event, question) => {
answerField.value = '';
questionField.innerText = question;
})
document.getElementById('submit').addEventListener('click', () => {
window.electronAPI.submitAnswer(answerField.value);
})
</script>
</html>

最新更新