Electron主进程如何等待renderer process返回用户答案
实现方案
核心逻辑不需要阻塞JS单线程,把「等待单题答案返回」封装为Promise对象,在循环中使用async/await等待Promise状态变更,既可以严格遵循「发送题目→等待用户作答→处理答案→发送下一题」的顺序执行,也不会阻塞事件循环,所有题目作答完成前不会执行后续逻辑。
主进程代码
const { BrowserWindow, ipcMain } = require('electron'); /** * 等待渲染进程返回当前题答案 * @returns {Promise<any>} 用户提交的答案 */ function waitForAnswer() { return new Promise((resolve) => { const answerHandler = (_, answerContent) => { // 收到答案后立刻移除监听,避免重复触发 ipcMain.off('submit-answer', answerHandler); resolve(answerContent); }; ipcMain.on('submit-answer', answerHandler); }); } // 答题流程标记为async函数,支持await语法 async function runQuizProcess() { const questions = []; // 替换为你的实际题目列表 const targetWindow = BrowserWindow.getAllWindows()[0]; const answerRecord = []; for (const singleQuestion of questions) { // 向渲染进程推送当前题目 targetWindow.webContents.send('new-question', { content: singleQuestion }); // 等待用户提交答案,不会阻塞线程,仅暂停当前函数执行让出事件循环 const userAnswer = await waitForAnswer(); // 对答案做自定义处理,比如存储、校验等 answerRecord.push({ question: singleQuestion, answer: userAnswer }); } // 所有题目答完才会执行到此处,写后续业务逻辑 console.log('答题流程结束,所有答案:', answerRecord); targetWindow.webContents.send('quiz-complete'); } // 在窗口加载完成后调用runQuizProcess()启动答题流程即可
渲染进程代码
1. Preload脚本(安全暴露IPC方法,不要直接开启渲染进程node权限)
// preload.js const { contextBridge, ipcRenderer } = require('electron'); contextBridge.exposeInMainWorld('quizAPI', { onNewQuestion: (renderCallback) => { ipcRenderer.on('new-question', (_, payload) => renderCallback(payload)); }, onQuizComplete: (renderCallback) => { ipcRenderer.on('quiz-complete', () => renderCallback()); }, submitAnswer: (answerContent) => { ipcRenderer.send('submit-answer', answerContent); } });
2. React组件逻辑
import { useState, useEffect } from 'react'; export default function QuizComponent() { const [currentQuestion, setCurrentQuestion] = useState(null); const [answerInput, setAnswerInput] = useState(''); const [isQuizFinished, setIsQuizFinished] = useState(false); useEffect(() => { // 监听主进程推送的新题目 window.quizAPI.onNewQuestion(({ content }) => { setCurrentQuestion(content); setAnswerInput(''); }); // 监听答题结束通知 window.quizAPI.onQuizComplete(() => { setIsQuizFinished(true); }); }, []); const handleSubmit = () => { if (!answerInput.trim()) return; window.quizAPI.submitAnswer(answerInput); }; if (isQuizFinished) return <div>全部题目作答完成</div>; if (!currentQuestion) return <div>题目加载中...</div>; return ( <div> <p>{currentQuestion}</p> <textarea value={answerInput} onChange={(e) => setAnswerInput(e.target.value)} placeholder="请输入答案" /> <button onClick={handleSubmit}>提交</button> </div> ); }
注意事项
- 禁止使用空while循环、固定间隔轮询的方式等待答案,这类写法会阻塞JS事件循环,直接导致应用无响应
- IPC事件监听要在收到结果后及时移除,避免重复绑定造成内存泄漏、回调多次触发的问题
- 如果需要处理答题中途用户关闭窗口的场景,可以在
waitForAnswer方法中增加窗口关闭事件监听,提前结束流程,避免Promise永久挂起
内容的提问来源于stack exchange,提问作者Mahmoud Mousa Hamad
相关产品推荐
相关产品推荐

