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

如何实现音频播放函数与异步函数的顺序循环执行?

解决方案

问题核心是你返回的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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 04:35:30