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

Foreach循环中变量hh存储的音频文件时长获取返回NaN问题求助

问题

在forEach循环中尝试获取存储在变量hh中的音频文件时长时,返回NaN而非预期值。音频文件已确认有效且可访问,但直接访问hh.duration始终得到NaN。简化代码如下:

function showcontent() {
    let songsarra = localStorage.getItem("Songs");
    let songa = JSON.parse(songsarra);
    
    document.getElementById("SongItemContainer").innerHTML = "";
    
    let x = 0;
    let index = 0;
    
    songa.forEach(()=>{
        let hh = new Audio(songa[x].filepath);        
        document.getElementById("SongItemContainer").innerHTML += `<div class="songItem">
        <img src="${songa[x].Coverpath}" alt="">
        <span class="songname">${songa[x].songName}</span>
        <span class="timestamp">${hh.duration} <i class="fa-regular fa-trash-can delete" onclick="deleteitem(${index})"></i> <i class="fa-regular  fa-circle-play current" id="${x}"></i></span>
        </div>`;
        x++;
        index++;
    });
}

原因与解决方案

问题根源

Audio对象的duration属性依赖于音频元数据的加载,创建Audio实例后立即访问duration时,元数据还未加载完成,因此返回NaN。

解决方法

1. 监听loadedmetadata事件获取时长

为每个Audio实例绑定loadedmetadata事件,待元数据加载完成后再更新DOM中的时长信息:

function showcontent() {
    let songsarra = localStorage.getItem("Songs");
    let songa = JSON.parse(songsarra);
    const container = document.getElementById("SongItemContainer");
    container.innerHTML = "";

    songa.forEach((song, idx) => {
        // 先创建并添加基础DOM元素
        const songItem = document.createElement("div");
        songItem.className = "songItem";
        songItem.innerHTML = `
            <img src="${song.Coverpath}" alt="">
            <span class="songname">${song.songName}</span>
            <span class="timestamp">加载中... <i class="fa-regular fa-trash-can delete" onclick="deleteitem(${idx})"></i> <i class="fa-regular fa-circle-play current" id="${idx}"></i></span>
        `;
        container.appendChild(songItem);

        // 创建Audio实例并监听元数据加载事件
        const audio = new Audio(song.filepath);
        audio.addEventListener("loadedmetadata", () => {
            // 格式化时长为MM:SS格式(可选)
            const minutes = Math.floor(audio.duration / 60);
            const seconds = Math.floor(audio.duration % 60);
            const formattedDuration = `${minutes}:${seconds.toString().padStart(2, "0")}`;
            // 更新对应的时长元素
            songItem.querySelector(".timestamp").innerHTML = `${formattedDuration} <i class="fa-regular fa-trash-can delete" onclick="deleteitem(${idx})"></i> <i class="fa-regular fa-circle-play current" id="${idx}"></i>`;
        });

        // 处理音频加载失败的情况
        audio.addEventListener("error", () => {
            songItem.querySelector(".timestamp").innerHTML = `加载失败 <i class="fa-regular fa-trash-can delete" onclick="deleteitem(${idx})"></i> <i class="fa-regular fa-circle-play current" id="${idx}"></i>`;
        });
    });
}

2. 优化循环写法

原代码中x和index变量完全多余,直接利用forEach的第二个参数(当前元素索引)即可,简化代码逻辑。

3. 避免频繁修改innerHTML

频繁拼接innerHTML会导致DOM反复重绘,性能较差,改用createElement和appendChild的方式更高效。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 19:22:36