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

如何用Async/Await等待媒体元素源更新以获取duration属性

问题:更新audio元素src后无法立即获取有效duration属性

使用原生JS、Web Audio API和Canvas开发音频可视化工具时,更新audio元素的src后,尝试立即读取duration属性返回NaN,但用setTimeout延迟50ms就能拿到有效值,希望找到更优雅的替代方案。

原代码如下:

async function chooseTrack(trackTxt) {
  audioElem.src = `tracks/${trackTxt}`;
  await audioElem.load()
}

async function updateAudioContext(trackTxt) {
  await audioCtx.suspend()
  .then(() =>  chooseTrack(trackTxt))
  .then(() => {
      console.log(audioElem)
      console.log(audioElem.duration) // 这里返回NaN
      frameLength = 360 / ((audioElem.duration * 1000)/ 3.2) ; 
      freqHeight = 250 / bufferLength;

  })
}

可行但不优雅的setTimeout方案:

setTimeout(() => {
  console.log(audioElem.duration) // 这里能拿到有效值
  frameLength = 360 / ((audioElem.duration * 1000)/ 3.2) ; 
  freqHeight = 250 / bufferLength;
}, 50)
解决方案

问题出在await audioElem.load()这一步:load()方法只是同步触发音频的加载流程,它本身不返回Promise,所以await不会等待元数据加载完成。duration属性只有在浏览器获取到音频元数据后才会变成有效值,对应的事件是loadedmetadata。

修改chooseTrack函数,让它返回一个Promise,等待loadedmetadata事件触发后再resolve:

function chooseTrack(trackTxt) {
  return new Promise((resolve) => {
    audioElem.src = `tracks/${trackTxt}`;
    // 监听loadedmetadata事件,确保只触发一次
    audioElem.addEventListener('loadedmetadata', resolve, { once: true });
    audioElem.load(); // 可选,设置src后浏览器会自动加载,调用load()可强制重新加载
  });
}

之后updateAudioContext函数可以正常使用await,此时后续代码就能拿到正确的duration:

async function updateAudioContext(trackTxt) {
  await audioCtx.suspend();
  await chooseTrack(trackTxt);
  // 这里duration已就绪
  console.log(audioElem.duration);
  frameLength = 360 / ((audioElem.duration * 1000)/ 3.2); 
  freqHeight = 250 / bufferLength;
}

补充说明

  • loadedmetadata事件在浏览器获取到音频的基础元数据(时长、码率等)时触发,是获取duration的最早时机。
  • 如果需要确保音频可以开始播放,可以监听canplay事件;如果需要确保大部分/全部音频加载完成,监听canplaythrough事件,但仅获取duration的话loadedmetadata足够。
  • 使用{ once: true }配置事件监听器,避免同一元素多次切换音频时出现重复监听的问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 21:56:12