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

setInterval获取lastChild异常及加载动效失效问题求助

加载动效异常问题分析与解决

问题现象

  • 首行动效失效:第一个加载项的动态三点效果无法显示
  • 最后一项状态异常:数组最后一项无法保持结尾带..!的完成状态

原代码

JavaScript代码

const randomDelay = ()=>{
    return new Promise((resolve,reject)=>{
        const timeout = (Math.random()*10)%7;
        setTimeout(() => {
            resolve();
        }, timeout*1000);
    });
}
const addItem = async(item)=>{
    let div = document.createElement("div");
    div.innerHTML = item;
    document.body.append(div);
    await randomDelay();
    div.innerHTML = item + "..!";
}

async function main() {
    let t = setInterval(() => {
        let last = document.body.lastChild;
        if(last.innerHTML.endsWith("...")){
            last.innerHTML = last.innerHTML.slice(0,last.innerHTML.length -3);
        }
        else{
            last.innerHTML += ".";
        }
    }, 300);
    let items = ["Initializing Hacking",
    "Reading your files",
    "Password Files Detected",
    "Sending all passwords and personal files to server",
    "Cleaning up"];
    // await randomDelay();
    for (const item of items) {
        await addItem(item);
    }
    await randomDelay();
    clearInterval(t);
}
console.log("look down here")
main();

HTML代码

<!DOCTYPE html>
<html>
<head></head>
<body>top</body>
</html>

问题原因

1. 首行动效失效

  • 定时器启动后,初始会操作body的第一个子节点(文本节点top),而第一个加载项的div被添加后,如果randomDelay生成的随机时间小于300ms(定时器首次执行时间),addItem会先将div修改为完成状态,导致定时器还没来得及操作该div,动效就被覆盖。
  • 取消注释await randomDelay()时,main函数会先等待一段随机时间,这段时间定时器持续操作top,等延迟结束后添加第一个div,此时randomDelay的时间足够让定时器多次操作新div,动效得以显示。

2. 最后一项状态异常

  • 最后一个addItem完成并将div设置为..!后,main函数还会执行await randomDelay(),此时定时器仍在运行,会继续修改该div的内容(给..!加.或删减),直到最后清除定时器,导致完成状态被破坏。

修复方案

修复后的JavaScript代码

const randomDelay = ()=>{
    return new Promise((resolve)=>{
        const timeout = (Math.random()*10)%7;
        setTimeout(resolve, timeout*1000);
    });
}
const addItem = async(item)=>{
    let div = document.createElement("div");
    div.innerHTML = item;
    document.body.append(div);
    await randomDelay();
    div.innerHTML = item + "..!";
    return div;
}

async function main() {
    let currentDiv = null;
    let t = setInterval(() => {
        // 只操作当前加载项的div,跳过已完成状态
        if (!currentDiv || currentDiv.innerHTML.includes("..!")) return;
        
        if(currentDiv.innerHTML.endsWith("...")){
            currentDiv.innerHTML = currentDiv.innerHTML.slice(0, -3);
        } else {
            currentDiv.innerHTML += ".";
        }
    }, 300);

    let items = ["Initializing Hacking",
    "Reading your files",
    "Password Files Detected",
    "Sending all passwords and personal files to server",
    "Cleaning up"];

    for (const item of items) {
        currentDiv = await addItem(item);
    }

    await randomDelay();
    clearInterval(t);
}

console.log("look down here")
main();

修复点说明

  1. 跟踪当前加载项:通过currentDiv变量直接跟踪正在加载的div,避免依赖body.lastChild,彻底解决初始文本节点干扰的问题。
  2. 跳过已完成状态:定时器回调中判断div是否包含..!,如果是则跳过操作,保证完成状态不会被修改。
  3. 返回创建的div:addItem函数返回创建的div,让main函数精准跟踪每个加载项,逻辑更可靠。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 17:48:09