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

视频源排队函数意外跳过数组元素:问题排查与修复

问题分析与修复方案

问题根源

  • 重复绑定事件导致逻辑混乱:每次调用test()时,都会在setInterval里重复给#player绑定timeupdate事件,随着循环执行会堆积大量事件监听。第一个视频结束触发test()后,旧的监听仍在运行,会误判第二个视频的播放状态,直接触发下一轮播放跳过第二个视频。
  • 视频结束判断逻辑不可靠:用currentTime == duration判断视频结束,会受timeupdate触发时机、浮点精度影响,大概率无法精准匹配,要么触发失效要么误触发。
  • 过早修改播放队列:在loadedmetadata事件里就移除数组首个元素,此时视频还未播放,若加载失败会直接丢失该视频资源。
  • 冗余定时器嵌套:用setInterval包裹事件绑定完全没必要,反而加剧了重复绑定的问题。

修复后的代码

核心优化:使用视频原生ended事件监听播放结束,避免重复绑定,调整队列修改时机,简化逻辑。

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<video id="player" muted autoplay></video>
video {
  width: 100%;
  height: 60vh;
}
const videoQueue = ["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"];
const $player = $('#player');

function playNext() {
  if (videoQueue.length === 0) {
    console.log('所有视频播放完毕');
    $player.off('ended');
    return;
  }
  // 先移除旧的事件监听,避免重复绑定
  $player.off('ended');
  // 设置当前播放源
  $player.attr('src', videoQueue[0]);
  // 绑定原生播放结束事件
  $player.on('ended', function() {
    // 确认播放完成后再移除队列首元素
    videoQueue.shift();
    playNext();
  });
}

// 启动播放队列
playNext();

关键优化说明

  • 用ended事件替代自定义判断:这是浏览器为video元素提供的原生事件,会在视频播放完成时精准触发,彻底规避自定义判断的精度和时机问题。
  • 避免事件监听堆积:每次启动新视频前,先移除之前的ended监听,防止多个监听同时触发导致逻辑混乱。
  • 合理修改队列时机:只有在视频确实播放完成后,才从队列中移除对应资源,避免加载失败导致视频丢失。
  • 简化逻辑结构:去掉冗余的定时器和不必要的事件嵌套,代码逻辑更清晰易维护。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 13:03:25