JavaScript异步函数未正确等待:列表同时渲染问题求助
问题说明
原本在typeOutText完成打字效果后,应先执行fadeInSlide3List1并等待其完成,再执行fadeInSlide3List2。添加Enter/空格键加速事件前,两个列表能按顺序渲染,但现在两者同时出现,调试数小时未找到原因。
相关代码
async function fadeInSlide3List1() { const slide3List1 = slide3Lists[0]; const container = document.querySelector(".design-list1"); container.style.visibility = "hidden"; let nextItemSpeed = 2000; for (let i = 0; i < slide3List1.length; i++) { const listItem = document.createElement("li"); listItem.textContent = slide3List1[i]; listItem.style.opacity = 0; listItem.style.transition = "opacity 1.5s"; container.appendChild(listItem); } container.style.visibility = "visible"; const fadeNextItem = async (index) => { if (index < slide3List1.length) { const listItem = container.children[index]; await new Promise((resolve) => setTimeout(resolve, nextItemSpeed)); listItem.style.opacity = 1; fadeNextItem(index + 1); } else { window.removeEventListener("keydown", handleKeyPress); } }; const handleKeyPress = (event) => { const keyPressed = event.key; if (keyPressed === "Enter" || keyPressed === " ") { nextItemSpeed = 500; fadeNextItem(0); } }; window.addEventListener("keydown", handleKeyPress); fadeNextItem(0); } async function fadeInSlide3List2() { const slide3List2 = slide3Lists[1]; const container = document.querySelector(".design-list2"); container.style.visibility = "hidden"; let nextItemSpeed = 2000; for (let i = 0; i < slide3List2.length; i++) { const listItem = document.createElement("li"); listItem.textContent = slide3List2[i]; listItem.style.opacity = 0; listItem.style.transition = "opacity 1.5s"; container.appendChild(listItem); } container.style.visibility = "visible"; const fadeNextItem = async (index) => { if (index < slide3List2.length) { const listItem = container.children[index]; await new Promise((resolve) => setTimeout(resolve, nextItemSpeed)); listItem.style.opacity = 1; fadeNextItem(index + 1); } else { window.removeEventListener("keydown", handleKeyPress); } }; const handleKeyPress = (event) => { const keyPressed = event.key; if (keyPressed === "Enter" || keyPressed === " ") { nextItemSpeed = 500; fadeNextItem(0); } }; window.addEventListener("keydown", handleKeyPress); fadeNextItem(0); } async function typeOutSlide3() { const slide3Lines = slideLines[2]; const content = slideContent[2]; if (content) { slide3Container.innerHTML = content; } else { let nextLineSpeed = typingSpeed; let delay = 1500; const renderNextLine = async (i) => { const line = slide3Lines[i]; await new Promise((resolve) => setTimeout(resolve, delay)); await typeOutText( slide3Container, line.text, nextLineSpeed, line.elementType, ); }; const handleKeyPress = (event) => { const keyPressed = event.key; if (keyPressed === "Enter" || keyPressed === " ") { window.removeEventListener("keydown", handleKeyPress); nextLineSpeed = 10; delay = 500; } }; window.addEventListener("keydown", handleKeyPress); for (let i = 0; i < slide3Lines.length; i++) { await renderNextLine(i); } slideContent[2] = slide3Container.innerHTML; } const paragraphs = slide3Container.getElementsByTagName("p"); if (paragraphs.length >= 2) { paragraphs[1].classList.add("second-p"); } await fadeInSlide3List1(); await fadeInSlide3List2(); }
问题根源与修复方案
核心问题
fadeInSlide3List1和fadeInSlide3List2是异步函数,但内部调用fadeNextItem(0)时未使用await,导致函数执行完同步代码就直接返回,不会等待整个列表淡入流程完成。因此await fadeInSlide3List1()实际上没等第一个列表渲染完,就直接执行了fadeInSlide3List2(),造成两者同时渲染。
另外还有两个次要问题:
- 递归调用
fadeNextItem(index + 1)时未加await,会导致递归流程无法正确等待,还可能引发未处理Promise警告。 - 按下Enter/空格时重复调用
fadeNextItem(0),会触发多个递归流程同时执行,导致加速逻辑混乱。
修复步骤
- 等待递归流程完成:在
fadeInSlide3List1和fadeInSlide3List2中,调用fadeNextItem(0)时添加await:
// 替换原代码中的 fadeNextItem(0); await fadeNextItem(0);
- 递归调用时等待:在
fadeNextItem的递归调用处添加await:
// 替换原代码中的 fadeNextItem(index + 1); await fadeNextItem(index + 1);
- 优化键盘事件逻辑:避免重复触发递归,只需修改速度即可,当前递归会自动使用新速度:
const handleKeyPress = (event) => { const keyPressed = event.key; if ((keyPressed === "Enter" || keyPressed === " ") && nextItemSpeed !== 500) { nextItemSpeed = 500; // 无需重新调用fadeNextItem(0),现有递归会自动用新速度继续执行 } };
修改完成后,await fadeInSlide3List1()会真正等待第一个列表完全淡入,再执行第二个列表的渲染,恢复原本的顺序执行逻辑。
内容的提问来源于stack exchange,提问作者Matthew Ford
相关产品推荐
相关产品推荐

