Need someone to help me understand, why index 2 of the playlist array that is passed to the audio element is skipped – no matter what. This is the console output:
0: /track01.mp3
1: /track02.mp3
2: /track03.mp3 // -> is logged but not played
3: /track01.mp3
4: undefined
(Note: It happens with whatever file is on index 2, so if I change the sequence of the files in the playlist array, still index 2 will be skipped.)
This is the code:
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)
}
})
}
So whatever audio file is on index 2 of the array – it will not be played. The console.log logs index 2, but the audio player skips to index 3, without having played index 2.
2
Answers
I think the issue lies in the condition in your
ended
event listener because after the song at index 2 finished playing,song_index
is incremented to 3 and condition(song_index) < playlist.length
evaluates to true becauseplaylist.length
is 4 hereby making a recursive call which results inplaySong(playlist)
being called again withsong_index
equal to 3.Try and adjust the condition in your
ended
event listener to check ifsong_index
is less thanplaylist.length - 1
. This ensures that the index does not go out of bounds and correctly plays all songs in the playlist:I suspect you’re running into issues of
canplay
firing or not firing when you don’t expect. Remember, this event can fire multiple times for the same files, and you’re actually using the same event handling even after switching files.There’s no need for all this. You can simplify your code by getting rid of
.load()
and thecanplay
handler, and just calling.play()
. It’s the behavior you’re looking for.