如何监听HTMLMediaElement(Audio)的播放结束事件?
监听音频播放完成的两种实用方案
嘿,这个需求太常见了!不用纠结ended属性的轮询方式,下面给你两种更优雅的实现思路,完全符合你想要的事件、Promise风格:
一、直接使用ended事件监听
这是HTML5 Audio元素原生支持的事件,当音频播放到末尾时会自动触发,简单又可靠:
const mySound = new Audio('/my-url'); mySound.play(); // 监听播放结束事件 mySound.addEventListener('ended', () => { console.log('音频已经播放完毕啦!'); // 在这里写下你需要执行的后续逻辑,比如播放下一首、更新UI等 });
如果后续需要移除监听,也可以用removeEventListener方法,灵活性拉满。
二、封装为Promise(现代异步编程风格)
如果你更喜欢用Promise/async-await的方式来处理异步流程,可以把音频播放和结束监听封装成一个Promise函数,这样代码会更整洁,也方便和其他异步操作配合:
function playAndWaitForEnd(url) { return new Promise((resolve, reject) => { const audio = new Audio(url); // 处理播放失败的情况 audio.play().catch(error => reject(`播放失败:${error.message}`)); // 监听播放结束事件,成功resolve audio.addEventListener('ended', () => { resolve('音频播放完成'); }); // 额外处理音频加载出错的情况 audio.addEventListener('error', (event) => { reject(`音频加载出错:${event.error.message}`); }); }); } // 使用方式1:then/catch playAndWaitForEnd('/my-url') .then(result => { console.log(result); // 播放结束后的逻辑 }) .catch(error => { console.error(error); }); // 使用方式2:async/await(更简洁) async function handleAudio() { try { await playAndWaitForEnd('/my-url'); console.log('音频播放完毕,开始执行后续操作'); // 这里写你的后续逻辑 } catch (error) { console.error('处理音频时出错:', error); } } handleAudio();
为什么不推荐用ended属性?
ended是一个布尔值属性,你需要通过定时轮询(比如setInterval)去检查它的状态,这种方式既浪费浏览器性能,代码也不够优雅。而事件监听是被动触发,只有当播放结束时才会执行回调,效率和可读性都高得多。
内容的提问来源于stack exchange,提问作者Valentin Coudert




