You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让函数执行完毕后再调用?Electron JS场景遇问题

如何让逐字动画函数执行完毕后再调用下一个

我需要实现逐字打印的动画效果,但两个TypeAnimation函数会同时执行,导致输出字符混乱——原本要依次打印first line of text和next line of text but slower,结果输出成finrset xlitne olf itenxte of text but slower。

尝试过用Promise和async/await,但问题依旧,相关代码如下:

初始代码

function TypeAnimation(str, time)
{    
    var text = document.getElementById('loading');

    for (let i = 0; i < str.length; i++) {
        let k = i;
        setTimeout(function(){
            text.innerHTML += str.charAt(i); 
        }, time * (k + 1));
    }
}

function StartGame()
{
    TypeAnimation('first line of text', 50)
    TypeAnimation('next line of text but slower', 100)
}

window.onload = StartGame;

尝试的Promise版本

function TypeAnimation(str, time)
{    
    return new Promise((resolve) => {

        var text = document.getElementById('loading');

        for (let i = 0; i < str.length; i++) {
            let k = i;
            setTimeout(function(){
                text.innerHTML += str.charAt(i); 
            }, time * (k + 1));
        }

        resolve();
    });
}

function StartGame()
{
    TypeAnimation('first line of text', 50).then(TypeAnimation('next line of text but slower', 100))
}

window.onload = StartGame;

尝试的async/await版本

async function StartGame()
{
    await TypeAnimation('first line of text', 50)
    TypeAnimation('next line of text but slower', 100)
}

问题根源

问题出在TypeAnimation的Promise实现里:resolve()是在for循环结束后立即执行的,根本没等所有setTimeout的回调执行完毕。这导致第一个函数的Promise马上变为resolved状态,第二个函数立刻启动,两个函数的定时器队列同时向DOM添加字符,最终造成输出混乱。


解决方案

要让Promise在所有字符打印完成后再resolve,有两种可靠的实现方式:

方案一:在最后一个字符的回调中触发resolve

修改TypeAnimation,在循环到最后一个字符时,执行完添加操作后调用resolve():

function TypeAnimation(str, time) {    
    return new Promise((resolve) => {
        const text = document.getElementById('loading');
        const totalChars = str.length;

        for (let i = 0; i < totalChars; i++) {
            setTimeout(() => {
                text.innerHTML += str.charAt(i);
                // 最后一个字符添加完成后resolve
                if (i === totalChars - 1) {
                    resolve();
                }
            }, time * (i + 1));
        }
    });
}

async function StartGame() {
    await TypeAnimation('first line of text', 50);
    // 添加换行让两行文本分开
    document.getElementById('loading').innerHTML += '<br>';
    await TypeAnimation('next line of text but slower', 100);
}

window.onload = StartGame;

方案二:计算总时长延迟resolve

如果不想在每个回调里做判断,也可以计算打印完所有字符的总时间,用额外的setTimeout延迟执行resolve():

function TypeAnimation(str, time) {    
    return new Promise((resolve) => {
        const text = document.getElementById('loading');

        for (let i = 0; i < str.length; i++) {
            setTimeout(() => {
                text.innerHTML += str.charAt(i);
            }, time * (i + 1));
        }

        // 总时长 = 单字符间隔 * 字符总数,延迟后resolve
        setTimeout(resolve, time * str.length);
    });
}

async function StartGame() {
    await TypeAnimation('first line of text', 50);
    document.getElementById('loading').innerHTML += '<br>';
    await TypeAnimation('next line of text but slower', 100);
}

window.onload = StartGame;

修改后,第一个函数会完整打印完所有字符后,才会启动第二个函数,输出不会再混乱。添加<br>可以让两行文本分开显示,效果更清晰。

内容的提问来源于stack exchange,提问作者thejoshbaker

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 07:30:48