异步循环/函数中无法获取正确索引,按钮点击事件仅触发首个按钮
问题根因
- 代码执行顺序受JS事件循环影响:
asyncTestFunction是异步函数,遇到await后会立即让出主线程,后续的事件绑定同步代码会先执行。此时index还处于初始值0,仅第一个按钮被绑定了点击事件。 - 后续异步循环更新
index的操作,不会自动触发新的事件绑定逻辑,因此第二个按钮始终没有绑定事件,无法触发点击回调。
修复方案
根据实际需求可以选择对应实现:
场景1:异步更新到对应索引时,再给对应按钮绑定事件
适合需要等异步逻辑跑完对应索引的任务后,才允许该按钮响应点击的场景:
const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms)); const btns = document.querySelectorAll('button') const btnsArr = [...btns]; const asyncTestFunction = async () => { for (let i = 0; i < btnsArr.length; i++) { await sleep(5000); // 拿到最新索引后直接绑定对应按钮的事件 btnsArr[i].addEventListener('click', () => { console.log(i, 'index - EventListener') }) console.log(i, '对应按钮事件绑定完成'); } } asyncTestFunction();
场景2:提前给所有按钮绑定事件,点击时读取最新的异步索引值
适合需要按钮从页面加载完成就可以点击,点击时能拿到最新的异步更新后的全局索引的场景:
const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms)); const btns = document.querySelectorAll('button') const btnsArr = [...btns]; let index = 0; const asyncTestFunction = async () => { for (let i = 0; i < 2; i++) { await sleep(5000); index = i; console.log(index, '全局索引更新完成'); } } asyncTestFunction(); // 页面加载完成后直接给所有按钮绑定事件 btnsArr.forEach((btn, btnIndex) => { btn.addEventListener('click', () => { console.log(`点击按钮的索引为:${btnIndex},当前全局最新索引为:${index}`) }) })
内容的提问来源于stack exchange,提问作者WalkMess
相关产品推荐
相关产品推荐

