Javascript 特定页面请求操作上的音频持续时间NaN
我一直在尝试使用HTML5和Jquery创建我的自定义媒体播放器 根据我刷新页面的方式,我采用了不同的方法并遇到了一些麻烦 第一例Javascript 特定页面请求操作上的音频持续时间NaN,javascript,jquery,html,html5-audio,Javascript,Jquery,Html,Html5 Audio,我一直在尝试使用HTML5和Jquery创建我的自定义媒体播放器 根据我刷新页面的方式,我采用了不同的方法并遇到了一些麻烦 第一例 $(document).ready(function(){ duration = Math.ceil($('audio')[0].duration); $('#duration').html(duration); }); 在这种情况下,当我通过按地址栏中的ENTER键将页面重定向到同一URL时,持续时间返回NaN。但是,当我使用reload按钮或按
$(document).ready(function(){
duration = Math.ceil($('audio')[0].duration);
$('#duration').html(duration);
});
在这种情况下,当我通过按地址栏中的ENTER
键将页面重定向到同一URL时,持续时间返回NaN。但是,当我使用reload按钮
或按F5
按钮刷新时,它可以完全正常工作
第二种情况
$(document).ready(function(){
duration = Math.ceil($('audio')[0].duration);
$('#duration').html(duration);
});
我在一些回答中读到,在loadedmetadata
事件之后加载持续时间可能会有所帮助。因此,我尝试了以下方法:
$(document).ready(function(){
$('audio').on('loadedmetadata', function(){
duration = Math.ceil($('audio')[0].duration);
$('#duration').html(duration);
});
});
令人惊讶的是,在这种情况下,第一种情况正好相反。在重定向的情况下,持续时间显示完全正常,即在地址栏中按ENTER键。但是,如果使用F5
按钮或重新加载按钮进行刷新,则根本不会显示持续时间,甚至不会显示NaN,这让我相信代码根本不会执行
进一步阅读表明,这可能是webkit浏览器中的一个bug,但我找不到任何结论性或有用的东西
这种奇怪行为背后的原因是什么?
如果你能解释一下这个问题的解决方案,那就太好了
编辑:
我主要在寻找行为差异背后的解释。我想了解在重定向和刷新的情况下呈现页面背后的机制 问题似乎在于事件处理程序设置得太晚,即音频文件在文档准备就绪之前加载了元数据
尝试通过删除$(文档)尽快设置事件处理程序。就绪
调用:
$('audio').on('loadedmetadata', function(){
duration = Math.ceil($('audio')[0].duration);
$('#duration').html(duration);
});
请注意,这要求
标记位于文档中的
标记之后
或者,您可以稍微调整逻辑,使更新持续时间的代码始终运行(但如果得到NaN
,则会优雅地失败):
根据这一点,这是duration返回NaN时的标准行为。
因此,我建议使用durationchange
事件:
$('audio').on('durationchange', function(){
var duration = $('audio')[0].duration;
if(!isNaN(duration)) {
$('#duration').html(Math.ceil(duration));
}
});
注意:如果页面上有多个audio
元素,则此代码(以及您的代码)将无法正常工作。原因是您从页面上的所有audio
元素收听事件,每个元素将触发自己的事件:
$('audio').on('durationchange', function(){...});
或
您可以尝试:
<script>
function durationchange() {
var duration = $('audio')[0].duration;
if(!isNaN(duration)) {
$('#duration').html(Math.ceil(duration));
}
}
</script>
<audio ondurationchange="durationchange()">
<source src="test.mp3" type="audio/mpeg">
</audio>
函数durationchange(){
var duration=$('audio')[0]。duration;
如果(!isNaN(持续时间)){
$('#duration').html(Math.ceil(duration));
}
}
请注意,不同浏览器的行为会有所不同。在Chrome上,您有不同类型的加载。当资源不在缓存中时
,它将获取完整的文件(例如js或css),或者文件的一部分(例如mp3)。此部分文件包含元数据
,允许浏览器确定持续时间和其他数据,如按此速率下载整个文件所需的时间,例如触发canplay
或canplaythrough
事件。如果您在dev控制台中查看网络使用情况,您将看到HTTP状态代码
将是200(成功加载)或206(部分加载-例如mp3)
当您点击刷新时,将检查元素是否更改。HTTP状态将是304
,这意味着该文件尚未修改。如果它没有更改并且仍在浏览器缓存中,则不会下载它。用于确定文件是否已更改的调用来自提供文件的服务器
当您只需单击地址栏中的enter键,它就会自动从缓存中获取,而不是在线验证。所以速度要快得多
因此,根据您调用或刷新页面的方式(无论是简单输入、刷新还是不带缓存的完全刷新),从mp3中获取元数据的那一刻,您会有很大的不同。直接从缓存获取元数据与向服务器发出请求之间的差异可能只有几百毫秒,这足以改变不同时刻可用的数据
也就是说,听loadedmetada
应该会得到一致的结果。此事件在加载具有持续时间信息的数据时触发,因此无论页面以何种方式加载,调用是否正确都不重要。在这一点上,你必须考虑到来自其他元素的干扰。你应该做的是通过各种事件跟踪你的音频,以准确地了解它在不同时刻的位置。因此,在DocumentReady中,您可以为不同的事件添加侦听器,并查看问题发生的位置。像这样:
$('audio')[0].addEventListener('loadstart', check_event)
$('audio')[0].addEventListener('loadeddata', check_event)
$('audio')[0].addEventListener('loadedmetadata', check_event)//at this point you should be able to call duration
$('audio')[0].addEventListener('canplay', check_event) //and so on
function check_event(e) {
console.log(e.target, e.type)
}
您将看到,根据刷新方式的不同,这些事件可能会在不同的时刻出现,可能会解释输出中的不一致性。可爱的代码示例和人们提供的东西-但解释实际上非常简单
如果文件已在缓存中,则不会触发loadedmetadata
事件(许多其他事件也不会触发-基本上是因为在连接侦听器时它们已经触发),并且将设置持续时间。如果它不在缓存中,则持续时间将为NaN
,事件将触发
解决办法有点简单
function runWhenLoaded() { /* read duration etc, this = audio element */ }
if (!audio.readyState) { // or $audio[0].readyState
audio.addEventListener("loadedmetadata", runWhenLoaded);
// or $audio.on("loadedmetadata", runWhenLoaded);
} else {
runWhenLoaded.call(audio);
// or runWhenLoaded.call($audio[0]);
}
我已经在代码注释中包含了jQuery备选方案。我会尝试一下,然后再给您回复。不。它仍然不起作用。最奇怪的是,与刷新页面相比,它在重定向情况下的行为方式有所不同。这两种方法在页面加载顺序方面有什么区别?是的,我已经尝试了三种不同的情况。