HTML Audio播放列表异常:索引2音频始终被跳过问题求助
HTML Audio播放列表跳过索引2音频的问题排查与修复
问题现象
播放列表数组中索引2位置的音频总是被跳过,控制台能打印该索引的音频路径,但实际未播放就直接跳至索引3的音频,甚至会出现索引4的undefined输出。即使调整播放列表内文件的顺序,索引2位置的音频仍无法正常播放。
原代码
let playlist = ["track01.mp3", "track02.mp3", "track03.mp3", "track01.mp3"] let song_index = 0 playSong(playlist) console.log(playlist) // contains 4 files function playSong(playlist){ console.log(`${song_index}: ${playlist[song_index]}`) audio_source.src = playlist[song_index] audio_source.load() audio_source.addEventListener("canplay", () => { audio_source.play() }) audio_source.addEventListener("ended", () => { if ((song_index) < playlist.length) { song_index++ playSong(playlist) } else { song_index = 0 playSong(playlist) } }) }
问题根源
- 重复绑定事件监听:每次调用
playSong都会给audio_source新增canplay和ended事件监听。当播放到索引2时,之前累积的ended事件会被多次触发,直接导致song_index连续递增,跳过当前音频。 - 索引边界判断错误:条件
if (song_index < playlist.length)存在逻辑问题。数组长度为4时,最大有效索引是3,当song_index=3时,3<4成立,song_index会被加至4,此时playlist[4]为undefined,就会出现控制台的undefined输出。
修复方案
修正后的代码
let playlist = ["track01.mp3", "track02.mp3", "track03.mp3", "track01.mp3"] let song_index = 0 // 只绑定一次ended事件,避免重复触发 audio_source.addEventListener("ended", () => { if (song_index < playlist.length - 1) { song_index++ } else { song_index = 0 } playSong(playlist) }) playSong(playlist) console.log(playlist) // contains 4 files function playSong(playlist){ console.log(`${song_index}: ${playlist[song_index]}`) audio_source.src = playlist[song_index] audio_source.load() // 使用once: true确保canplay事件只触发一次 audio_source.addEventListener("canplay", () => { audio_source.play() }, { once: true }) }
关键修复点
- 移除重复事件绑定:将
ended事件监听移到playSong函数外部,只绑定一次,避免多次触发导致索引跳步。 - 修正索引边界判断:把条件改为
song_index < playlist.length - 1,确保当song_index到达最后一个有效索引(3)时,直接重置为0,而不是递增到4。 - 限制canplay事件触发次数:给
canplay事件添加{ once: true }选项,确保每次加载音频时只触发一次播放,避免重复播放逻辑干扰。
内容的提问来源于stack exchange,提问作者nBar
相关产品推荐
相关产品推荐

