You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.30 22:42:22