如何用JavaScript实现文字冒险游戏输入等待及合法选项校验功能
问题原因
你的原有实现和尝试的思路存在两个核心缺陷:
- JS为单线程运行模型,同步while循环会持续占用主线程,阻塞UI渲染和所有事件响应,直接导致页面卡顿卡死
- list函数每次调用都会新增keyup事件绑定,没有做好旧事件清理,会出现事件重复触发、函数被调用数千次的异常
正确实现方案
我们用Promise封装整个输入校验的异步流程,替代同步循环避免主线程阻塞:
// 作用域内提前声明变量,可根据你的实际代码结构调整作用域 let timeout; const input = document.querySelector('input'); // 替换为你实际的input DOM元素 /** * 等待用户输入完成并返回合法选项 * @param {Array} validKeys 合法输入的枚举值,示例场景传['a','b']即可 * @returns {Promise<string>} 用户最终输入的合法值 */ function waitForValidChoice(validKeys) { return new Promise((resolve) => { // 每次调用前先清理旧事件、旧定时器,避免重复绑定 input.removeEventListener('keyup', handleInput); clearTimeout(timeout); input.value = ''; input.focus(); function handleInput(e) { clearTimeout(timeout); // 停止输入1秒视为输入完成,可根据需求调整时长 timeout = setTimeout(() => { const inputVal = input.value.trim().toLowerCase(); input.value = ''; // 校验输入合法性 if (validKeys.includes(inputVal)) { input.removeEventListener('keyup', handleInput); resolve(inputVal); } // 输入不合法则自动保持监听状态,无需额外操作 }, 1000); } input.addEventListener('keyup', handleInput); }); }
调用示例
对应你的洞穴/山脉选择场景,直接异步调用即可:
async function startAdventureChoice() { // 此处替换为你实际渲染剧情文本的逻辑 console.log('你想要前往洞穴还是山脉?'); console.log('a)洞穴'); console.log('b)山脉'); // 等待用户输入合法选项 const userChoice = await waitForValidChoice(['a', 'b']); // 走对应剧情分支 if (userChoice === 'a') { // 洞穴剧情逻辑 console.log('你踏入了幽暗的洞穴...'); } else { // 山脉剧情逻辑 console.log('你向着连绵的山脉出发...'); } } // 启动选择流程 startAdventureChoice();
方案优势
- 全异步实现,不会阻塞主线程,无页面卡顿问题
- 每次调用自动清理旧事件和定时器,不会出现重复触发的异常
- 支持自定义合法选项,后续其他选择场景直接传不同参数即可复用
- 自动兼容用户大小写输入,使用体验更好
内容的提问来源于stack exchange,提问作者anymany
相关产品推荐
相关产品推荐

