JavaScript中如何确保repeatPatternColor的所有动画执行完成后再调用generateColor?
JavaScript中如何确保repeatPatternColor的所有动画执行完成后再调用generateColor?
嘿,我明白你的困扰啦!你现在遇到的问题核心在于Promise的resolve时机不对——你的repeatPatternColor和generateColor里的Promise都提前完成了,根本没等里面的动画定时器执行完,所以await自然起不到等待的作用。咱们一步步来解决:
首先修复repeatPatternColor的问题
你现在的代码里,for循环一结束就立刻调用了resolve(),但循环里的所有setTimeout都是异步任务,循环结束时这些定时器甚至还没开始执行呢!所以Promise直接标记为完成,await也就跳过等待,直接去执行generateColor了。
推荐用更直观的async/await写法来封装循环内的异步操作,逻辑清晰不容易出错:
// 先封装一个通用的等待函数,把setTimeout转成Promise function wait(ms) { return new Promise(resolve => setTimeout(resolve, ms)); } async function repeatPatternColor(pattern) { for (let i = 0; i < pattern.length; i++) { // 等待当前迭代的初始延迟 await wait((i + 1) * delayMileSec); const color = pattern[i]; const singleCol = document.getElementById(color); // 添加高亮类,等待动画时长 singleCol.classList.add(`${color}-light`); await wait(delayMileSec); // 移除高亮类,完成当前迭代的动画 singleCol.classList.remove(`${color}-light`); console.log(color); } }
这样每一次循环的动画都会按顺序执行,整个函数会在所有循环的动画都完成后才结束,await就能正确等待了。
然后调整generateColor的resolve时机
你这里同样犯了Promise提前resolve的错误——resolve()写在了setTimeout外面,导致Promise在动画还没结束时就完成了。我们需要把resolve()移到setTimeout的回调里,确保动画完成后才标记Promise完成:
function generateColor() { return new Promise((resolve) => { disableDivs(); const randomNum = Math.floor(Math.random() * 4); const id = color[randomNum].id; pattern.push(id); const singleCol = document.getElementById(id); singleCol.classList.add(`${id}-light`); setTimeout(function () { singleCol.classList.remove(`${id}-light`); enableDivs(); console.log("Pattern: " + pattern); resolve(); // 动画全部完成后再resolve }, 1000); }); }
调用部分无需修改
你原来的fnAsync写法是对的,只要上面两个函数的Promise处理正确,await就会严格按顺序等待:
async function fnAsync() { await repeatPatternColor(pattern); await generateColor(); } let response = fnAsync();
这样修改后,generateColor就会等到repeatPatternColor里的所有动画都执行完成后才开始运行啦!
备注:内容来源于stack exchange,提问作者Arian Gorani
相关产品推荐
相关产品推荐

