如何实现音频播放函数与异步函数的顺序循环执行?
解决方案
问题核心是你返回的Promise从未被正确触发resolve,导致await一直处于挂起状态,后续代码无法执行。Audio.play()仅负责启动播放,不会自动告知播放完成,必须通过监听音频的ended事件来确认播放结束,同时还要处理加载、播放失败的异常情况,避免Promise一直处于pending状态。
1. 修复playSong函数
让它返回一个Promise,在音频播放完成时resolve,出错时reject:
const [song] = useState(typeof Audio !== 'undefined' && new Audio()) function playSong(songNum) { return new Promise((resolve, reject) => { // 先移除旧的事件监听,避免重复绑定 song.removeEventListener('ended', onEnded) song.removeEventListener('error', onError) function onEnded() { resolve() // 清理监听 song.removeEventListener('ended', onEnded) song.removeEventListener('error', onError) } function onError(e) { reject(e) // 清理监听 song.removeEventListener('ended', onEnded) song.removeEventListener('error', onError) } song.src = songs[songNum] song.load() // 处理播放失败(比如浏览器自动播放限制) song.play().catch(err => { reject(err) song.removeEventListener('ended', onEnded) song.removeEventListener('error', onError) }) }) }
2. 调整finalFunction执行逻辑
用await按顺序执行,避免嵌套then,保持代码简洁:
async function finalFunction() { for (let i = 0; i < songs.length; i++) { try { // 等待当前音频播放完成 await playSong(i) // 音频播放结束后执行异步函数 const res = await secondFunction() console.log(res) } catch (err) { // 处理音频播放失败的情况 console.error('音频播放出错:', err) } } }
关键说明
- 必须监听
ended事件来确认播放完成,不能仅依赖play()的返回值,因为play()只是启动播放,不代表播放结束。 - 每次调用
playSong时要移除旧的事件监听,避免多次绑定导致重复触发resolve。 - 添加错误处理,防止音频加载/播放失败时Promise一直pending,导致循环卡住。
内容的提问来源于stack exchange,提问作者JohnPix
相关产品推荐
相关产品推荐

