如何修复JavaScript中Firestore随机题目不等待Next按钮直接全部展示的问题
嘿,我完全懂你遇到的问题!你现在的代码里,runningExam函数的while循环会一口气把所有题目请求并渲染完——因为循环是同步执行的,Firestore的请求一完成就立刻调用renderQuestion,整个过程瞬间跑完,根本不会等用户点击Next按钮。
要解决这个问题,我们得换个思路:先把所有随机顺序的题目提前准备好,然后让Next按钮来控制逐个渲染,而不是让循环自动跑完所有步骤。下面是具体的修复方案:
核心思路
- 先一次性获取所有需要的题目,按随机顺序存入数组
- 维护一个「当前题目索引」,初始从0开始,先渲染第一题
- 给Next按钮绑定点击事件,每次点击就切换到数组里的下一题
修改后的代码
// 全局/闭包内存储题目列表和当前索引(根据你的代码结构调整作用域) let questionsList = []; let currentQuestionIndex = 0; // 简化渲染函数,只需要传入题目文档即可 renderQuestion = (qDoc) => { q.innerHTML = qDoc.data().question; ans1.innerHTML = qDoc.data().a; ans2.innerHTML = qDoc.data().b; ans3.innerHTML = qDoc.data().c; ans4.innerHTML = qDoc.data().d; }; // Next按钮的点击逻辑单独封装 function handleNextClick() { currentQuestionIndex++; if (currentQuestionIndex < questionsList.length) { // 还有题目,渲染下一题 renderQuestion(questionsList[currentQuestionIndex]); } else { // 所有题目展示完毕,做收尾处理 q.innerHTML = "考试结束!"; next.disabled = true; // 禁用按钮防止重复点击 } } runningExam = async (review) => { const totalQ = review.data().total_questions; let arr = []; // 初始化标记数组,避免重复选同一题 for (let i = 0; i <= totalQ; i++) { arr.push(false); } let n = totalQ; // 先收集所有随机选中的题目文档 while (n) { let randomNumber = getRandom(totalQ); if (!arr[randomNumber]) { arr[randomNumber] = true; const snapshot = await db .collection("examrooms") .doc(review.id) .collection("questions") .where("serial", "==", randomNumber) .get(); // 因为serial是唯一序号,所以取第一个文档即可 if (snapshot.docs.length > 0) { questionsList.push(snapshot.docs[0]); } n--; } } // 渲染第一题,并绑定Next按钮事件(确保只绑定一次) if (questionsList.length > 0) { renderQuestion(questionsList[currentQuestionIndex]); next.removeEventListener("click", handleNextClick); next.addEventListener("click", handleNextClick); } };
关键改动说明
- 去掉了原代码里循环内直接渲染的逻辑,改为先把所有题目存入
questionsList数组 - 用
currentQuestionIndex记录当前显示的题目位置,通过Next按钮点击来推进索引 - 单独封装
handleNextClick函数处理切换逻辑,避免重复绑定事件 - 因为
serial是唯一的题目序号,所以不需要用forEach遍历snapshot,直接取第一个文档即可
这样修改后,程序会先渲染第一题,只有当用户点击Next按钮时,才会展示下一题,完全符合你的预期啦!
内容的提问来源于stack exchange,提问作者mahin
相关产品推荐
相关产品推荐

