为何我的async函数未正常工作?JS弹窗事件绑定异常排查
问题原因
alretMaker虽标记为async函数,但内部依赖的setInterval是异步定时器,且函数本身没有返回可等待的Promise。await alretMaker()会直接跳过等待,立刻执行后续的spanMaker——此时弹窗还未全部生成,document.querySelectorAll('span')无法获取到所有关闭按钮,导致事件绑定失效。- 手动执行
spanMaker时,弹窗已全部生成,自然能获取到完整的span元素集合,事件绑定正常生效。
修复方案
修改 alretMaker,让它返回一个Promise,在所有弹窗生成完成(定时器被清除时)resolve这个Promise,同时优化变量作用域避免全局污染:
let thoughts = ['1', '2', '3', '4', '5'] // 修正拼写:alret → alert(建议规范命名) const alertMaker = async () => { return new Promise((resolve) => { let i = 0; // 将i放在函数内部,避免全局变量冲突 const interval = setInterval(() => { const div = document.createElement('div') const alert = document.createElement('span') document.body.append(div) div.append(alert) div.className = 'alert primary' alert.className = 'close' alert.innerText = '×' div.append(thoughts[i]) i++; if (i >= thoughts.length) { clearInterval(interval) resolve() // 所有弹窗生成完毕,通知Promise完成 } }, 1000) }) } const spanMaker = () => { // 无异步操作,无需标记async const spans = document.querySelectorAll('span.close') // 精准选择关闭按钮 for (let span of spans) { span.addEventListener('click', () => { span.parentElement.style.display = 'none' }) } } const runCode = async () => { await alertMaker() spanMaker() // 同步函数无需await } runCode()
更优方案:事件委托
无需等待弹窗生成,直接用事件委托绑定一次事件即可处理所有现有和未来的关闭按钮:
let thoughts = ['1', '2', '3', '4', '5'] const alertMaker = async () => { return new Promise((resolve) => { let i = 0; const interval = setInterval(() => { const div = document.createElement('div') const alert = document.createElement('span') document.body.append(div) div.append(alert) div.className = 'alert primary' alert.className = 'close' alert.innerText = '×' div.append(thoughts[i]) i++; if (i >= thoughts.length) { clearInterval(interval) resolve() } }, 1000) }) } // 事件委托:监听document点击,判断目标是否为关闭按钮 document.addEventListener('click', (e) => { if (e.target.classList.contains('close')) { e.target.parentElement.style.display = 'none' } }) const runCode = async () => { await alertMaker() } runCode()
这种方式无需单独执行spanMaker,性能更优,也避免了元素生成时机的问题。
内容的提问来源于stack exchange,提问作者Murtaza Alkabie
相关产品推荐
相关产品推荐

