JavaScript倒计时归零时Alarm报警音频重复播放问题
问题根因
代码存在两个逻辑缺失,才会导致音频重复播放:
- 没有给音频播放加触发条件:
setInterval会每秒执行一次updateCountdown,如果你直接把audio.play()写在这个函数里,没有绑定「时间归零」的判断,函数每跑一次就会触发一次播放,自然每秒都响 - 时间归零后没有停止定时器:就算加了归零判断,如果不清除持续运行的定时器,后续每次定时器触发还是会走到播放逻辑,重复触发音频
修复方案
- 首先保存
setInterval返回的定时器ID,方便时间归零时彻底停止循环任务 - 在
updateCountdown的时间计算逻辑里,当时间递减到0时,先清除定时器,再触发音频播放,保证播放逻辑只会执行一次 - 如果需要报警音持续循环,直接设置音频对象的
loop属性即可,不要依赖定时器重复调用播放方法
修复后可直接运行的代码
let time = startingMinutes * 60; const countdownEl = document.getElementById('Countdown'); // 保存定时器ID用于后续清除 const countdownTimer = setInterval(updateCountdown, 1000); // 初始化音频 const audio = new Audio(); audio.src = "alarm.mp3"; // 需要报警音循环播放就取消下面这行的注释 // audio.loop = true; function updateCountdown () { const minutes = Math.floor(time / 60); let seconds = time % 60; // 秒数补0 seconds = seconds < 10 ? '0' + seconds : seconds; countdownEl.innerHTML = `${minutes}:${seconds}`; time--; // 时间归零判断 if (time < 0) { time = 0; // 清除定时器,停止每秒执行的回调 clearInterval(countdownTimer); // 触发报警音,加catch处理浏览器自动播放限制的报错 audio.play().catch(err => { console.warn('音频自动播放被浏览器拦截,请用户先与页面产生交互后再启动倒计时', err); }); } }
补充说明
- 现代浏览器默认禁止无用户交互的页面自动播放音频,建议给倒计时加一个启动按钮,用户点击按钮后再开始计时、初始化音频,就能避免播放被拦截的问题
- 播放逻辑必须放在
time < 0的判断分支内部,不要放在分支外,否则还是会被每秒执行的定时器重复触发
内容的提问来源于stack exchange,提问作者Donut
相关产品推荐
相关产品推荐

