为何点击按钮需三次才能正常重启Promise循环?求修复方案
问题修复:Promise循环暂停/恢复异常处理
问题根源
当前代码的核心问题是每次调用pauser()都会给按钮新增一个点击事件监听器,导致多次点击后事件触发逻辑混乱:
- 第一次暂停时,按钮绑定了一个点击事件
- 恢复运行时又绑定了新的事件处理函数,第二次点击会同时触发多个事件,导致
stop状态被反复切换,最终出现循环仅运行一次就再次暂停的异常
修复方案
- 将按钮点击事件的绑定逻辑移出
pauser(),仅在初始化时绑定一次,避免重复绑定 - 调整
pauser()的逻辑,仅在需要等待恢复时临时添加监听,恢复后立即移除监听 - 修正循环变量的作用域,避免全局变量污染
修改后的完整代码
// 初始化全局状态和DOM元素 let stop = false; const pausebutton = document.getElementById('pausebutton'); const word = document.getElementById('word'); const text_words = ['word1', 'word2', 'word3']; // 示例文本数组 const some_length = text_words.length; // 按钮点击事件仅绑定一次,负责切换状态和文本 pausebutton.addEventListener('click', () => { stop = !stop; pausebutton.innerHTML = stop ? 'Start' : 'Stop'; }); // 定时器工具函数 const timer = ms => new Promise(res => setTimeout(res, ms)); // 优化后的暂停等待函数 function pauser() { return new Promise(resolve => { // 如果已经是运行状态,直接结束等待 if (!stop) { resolve(); return; } // 定义临时监听函数:当状态变为运行时,移除监听并resolve const handleResume = () => { if (!stop) { pausebutton.removeEventListener('click', handleResume); resolve(); } }; // 添加临时监听,等待恢复操作 pausebutton.addEventListener('click', handleResume); }); } // 主循环函数 async function program_loop() { // 给循环变量添加let声明,避免全局作用域污染 for (let word_iterator = 0; word_iterator < some_length; word_iterator++) { // 若处于暂停状态,等待恢复 if (stop) await pauser(); // 更新显示内容 word.innerHTML = text_words[word_iterator]; await timer(200); } } // 启动循环 program_loop();
关键修复点说明
- 单次事件绑定:按钮的状态切换逻辑只初始化一次,避免多次绑定导致的事件堆叠
- 临时监听机制:
pauser()仅在需要等待时添加监听,恢复后立即移除,确保每次等待只会响应一次恢复操作 - 变量作用域修正:
word_iterator使用let声明,限定在循环作用域内,避免全局变量导致的循环异常
内容的提问来源于stack exchange,提问作者Mats
相关产品推荐
相关产品推荐

