如何在while循环中用async/await接收按钮点击且不阻塞?
解决方案
核心思路是创建一个可复用的Promise生成函数,每次需要等待用户输入时,生成一个新的Promise,并用按钮点击事件来resolve这个Promise。同时通过ready_for_input开关控制是否响应点击,避免无效输入干扰游戏流程。
步骤1:重构按钮点击逻辑与Promise生成
把按钮点击事件的处理和Promise的resolve绑定,同时只在游戏准备好接收输入时才处理点击:
// 存储当前等待用户输入的Promise的resolve函数 let resolveInputPromise; function handleButtonClick(e) { // 只有游戏准备好接收输入时才处理 if (!Game.ready_for_input) return; // 拿到点击的按钮标识,这里用按钮文本示例 const inputValue = e.target.textContent; // 如果当前有等待中的Promise,就resolve它并传入点击值 if (resolveInputPromise) { resolveInputPromise(inputValue); resolveInputPromise = null; // 重置,避免重复触发 } } // 给两个按钮绑定点击事件 document.getElementById('button1').addEventListener('click', handleButtonClick); document.getElementById('button2').addEventListener('click', handleButtonClick); // 生成等待用户输入的Promise的函数 function waitForUserInput() { return new Promise((resolve) => { // 把resolve函数存到全局变量,让点击事件能访问到 resolveInputPromise = resolve; }); }
步骤2:修改游戏循环与play_round函数
调整play_round里的逻辑,用await waitForUserInput()来等待点击,同时修正外层的游戏循环(必须用async/await,否则会无限制创建异步任务导致阻塞):
var Game = { ready_for_input: false, game_over: false, play_round: async function () { // 示例:初始化回合状态 let round_not_yet_won = true; let win = false; // 这里写你的回合初始化逻辑、初始胜利条件检查 console.log("新回合开始"); if (round_not_yet_won) { this.ready_for_input = true; while (round_not_yet_won) { // 等待用户点击按钮,拿到点击的值 const userInput = await waitForUserInput(); // 这里写你的输入后的条件检查逻辑 console.log("用户点击了:", userInput); // 示例:假设点击按钮1获胜 if (userInput === "1") { win = true; round_not_yet_won = false; this.ready_for_input = false; console.log("回合获胜!"); return; } else { console.log("没猜对,继续尝试"); // 可添加失败后的逻辑,比如扣分、提示等 } } } } }; // 修正外层游戏循环:用async函数包裹,并用await调用play_round async function startGame() { while (!Game.game_over) { await Game.play_round(); // 这里可添加回合结束后的逻辑,比如判断游戏是否结束 // 示例:玩3回合后游戏结束 // static roundCount = 0; // Game.roundCount++; // if (Game.roundCount >= 3) Game.game_over = true; } console.log("游戏结束"); } // 启动游戏 startGame();
关键说明
- 避免页面阻塞:用
await waitForUserInput()代替同步等待,让浏览器在等待点击时可以正常处理渲染、其他交互事件,不会卡死页面。 - 输入有效性控制:通过
ready_for_input开关,确保只有在游戏需要用户输入的阶段才响应按钮点击,避免用户在回合初始化、结算阶段的无效操作。 - Promise精准绑定:每次进入等待输入阶段都会生成新的Promise,点击事件触发时resolve对应的Promise,确保每一次等待都匹配正确的用户输入。
内容的提问来源于stack exchange,提问作者defterGoose
相关产品推荐
相关产品推荐

