如何在easeInOut函数执行完毕后调用spawnBug函数?
问题
我有一个主函数play(),它会先调用easeInOut函数。这个easeInOut依赖setTimeout实现动画,还嵌套了toggleFade函数。我需要等easeInOut完全执行完毕后再调用spawnBug——因为easeInOut会将目标div的display设为flex并设置宽高,只有执行完成后才能获取它的clientWidth和clientHeight。
现有代码:
function easeInOut(elementOut, elementIn, fadeTime) { elementOut.classList.toggle("fade"); setTimeout(() => { elementOut.style.display = "none"; toggleFade(elementIn); }, fadeTime); function toggleFade(elemIn) { elemIn.style.display = "flex"; // 这一步后才能获取div的clientWidth/Height setTimeout(() => { elemIn.classList.toggle("fade"); }, fadeTime); }}
主函数:
function play() { easeInOut(selectContainer, gameInterface, 100); spawnBug(100); // 希望这行在上面的函数完全执行完再运行 }
解决方案
要让异步执行的easeInOut完成后再触发spawnBug,可以通过Promise+异步等待或回调函数两种方式实现,以下是具体方案:
方案1:Promise + async/await(推荐)
改造easeInOut让它返回一个Promise,在所有异步动画完成后标记任务结束:
function easeInOut(elementOut, elementIn, fadeTime) { return new Promise((resolve) => { elementOut.classList.toggle("fade"); setTimeout(() => { elementOut.style.display = "none"; toggleFade(elementIn); function toggleFade(elemIn) { elemIn.style.display = "flex"; setTimeout(() => { elemIn.classList.toggle("fade"); // 所有异步操作完成,通知Promise结束 resolve(); }, fadeTime); } }, fadeTime); }); }
将play改为异步函数,用await等待easeInOut执行完毕:
async function play() { await easeInOut(selectContainer, gameInterface, 100); spawnBug(100); // 现在会在easeInOut完全执行后再调用 }
方案2:回调函数
给easeInOut添加回调参数,在动画最后一步执行回调:
function easeInOut(elementOut, elementIn, fadeTime, callback) { elementOut.classList.toggle("fade"); setTimeout(() => { elementOut.style.display = "none"; toggleFade(elementIn); function toggleFade(elemIn) { elemIn.style.display = "flex"; setTimeout(() => { elemIn.classList.toggle("fade"); // 执行传入的回调函数 typeof callback === 'function' && callback(); }, fadeTime); } }, fadeTime); }
调用时将spawnBug作为回调传入:
function play() { easeInOut(selectContainer, gameInterface, 100, () => { spawnBug(100); }); }
两种方案都能满足需求,Promise+async/await的写法更符合现代JavaScript异步编程规范,代码可读性更强。
内容的提问来源于stack exchange,提问作者Alexandru Kullman
相关产品推荐
相关产品推荐

