I am trying to make a simple queue system that plays videos turn by turn. The video source is stored inside an array. The below code has a function that gets the first index element from the array plays that video, then removes that item from the array. It repeats the same method again and again until no elements are found inside the array.
It plays the first video as intended, but then skips the second video (array element) and plays the third. Where did I go wrong and how can I fix it?
myArr = ["http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/ForBiggerJoyrides.mp4", "http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/ForBiggerMeltdowns.mp4", "http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/ForBiggerFun.mp4"]
function test() {
$('#player').attr('src', myArr[0])
$("#player").on("loadedmetadata", function() {
myArr = myArr.slice(1)
var onEnd = setInterval(() => {
$("#player").on("timeupdate", function() {
var cTime = this.currentTime;
var dur = this.duration;
//console.log(cTime, dur)
//check if video finished playing
if (cTime == dur) {
console.log('video Ended')
if (myArr.length != 0) {
clearInterval(onEnd)
test()
} else {
clearInterval(onEnd)
console.log('all videos played')
}
}
});
}, 500)
})
}
test()
video {
width: 100%;
height: 60vh;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<video id="player" muted autoplay></video>
>Solution :
In the case that not all videos were played yet, you call the test
function again. But this function sets an event listener for loadedmetadata
, and that listener advances the array by one. By calling test
multiple times, you are setting multiple event listeners for the loadedmetadata
event, each of which will fire and advance the array. You need to restructure your code such that the listener is only attached once.