不使用JS库或Node.js 循环获取数组内MP3时长遇NaN如何解决
问题原因
- 设置audio元素的
src后,音频元数据加载是浏览器异步执行的,你同步读取duration时元数据还未加载完成,所以返回NaN。 - 遍历数组时仅能拿到最后一个MP3的时长,是因为循环过程中你同步修改了同一个audio元素的src,循环执行完毕时src已经被覆盖为数组最后一项的地址,前面绑定的
onloadedmetadata事件触发时,读取的都是最终的src对应的元数据。
修复方案
用Promise封装单条音频的元数据加载逻辑,配合async/await按顺序迭代数组,保证前一个音频加载完成、拿到时长后再处理下一个条目,示例代码如下:
// 你的歌曲数组,可根据实际格式调整 const songList = [ { artistName: "示例歌手1", songName: "示例歌曲1" }, { artistName: "示例歌手2", songName: "示例歌曲2" } ] const getDuration = document.querySelector('.preload-audio') // 封装单个音频元数据加载方法 function loadSingleAudio(artist, song) { return new Promise((resolve, reject) => { getDuration.src = `static/mp3/${artist} - ${song}.mp3` getDuration.onloadedmetadata = () => { resolve({ artist: artist, song: song, duration: getDuration.duration // 单位为秒 }) } getDuration.onerror = (err) => { reject(new Error(`音频${artist} - ${song}加载失败: ${err.message}`)) } }) } // 按顺序批量获取所有音频时长 async function getAudioDurations() { const result = [] // 用for of配合await保证顺序执行 for (const songItem of songList) { try { const audioMeta = await loadSingleAudio(songItem.artistName, songItem.songName) result.push(audioMeta) // 此处可添加单条音频处理逻辑 console.log(audioMeta) } catch (err) { console.error(err) } } // 所有条目处理完成后可拿到全部结果 console.log('全部时长获取完成:', result) } // 启动执行 getAudioDurations()
如果不需要保留加载顺序,也可以给每个音频创建独立的audio元素并行加载,速度会更快,但会占用更多内存。
内容的提问来源于stack exchange,提问作者vvhitearmor
相关产品推荐
相关产品推荐

