音频对象持续时间不断变化?



我试图获取列表中每个对象的持续时间(以秒为单位(,但我的结果遇到了一些问题。我认为这是因为我没有完全理解异步行为。

我用一个数组songs[]n对象开始我的函数。在我的函数结束时,目标是有一个数组songLengths其中第一个值是songs[]中第一个对象的持续时间,依此类推。

我正在尝试根据此示例对我的函数进行建模:循环内的JavaScript闭包 - 简单的实际示例。但是我得到了每个songLengths[]索引的未定义值。

$("#file").change(function(e) {
var songs = e.currentTarget.files;
var length = songs.length;
var songLengths = [];
function createfunc(i) {
return function() {
console.log("my val = " + i);
};
}
for (var i = 0; i < length; i++) {
var seconds = 0;
var filename = songs[i].name;
var objectURL = URL.createObjectURL(songs[i]);
var mySound = new Audio([objectURL]);
mySound.addEventListener(
"canplaythrough",
function(index) {
seconds = index.currentTarget.duration;
},
false,
);
songLengths[i] = createfunc(i);
}
});

这样的东西应该在没有混乱的闭包的情况下工作,并且由于承诺而增加了干净的异步性。

基本上我们声明了一个辅助函数,computeLength,它采用 HTML5File并执行您已经做的魔术来计算其长度。 (尽管我确实添加了URL.revokeObjectURL调用以避免内存泄漏。

但是,承诺不是只返回持续时间,而是使用包含原始文件对象和计算的持续时间的对象进行解析。

然后在事件处理程序中,我们映射选择从中创建computeLength承诺的files,并使用Promise.all等待所有这些承诺,然后记录生成的[{file, duration}, {file, duration}, ...]数组。

function computeLength(file) {
return new Promise((resolve) => {
var objectURL = URL.createObjectURL(file);
var mySound = new Audio([objectURL]);
mySound.addEventListener(
"canplaythrough",
() => {
URL.revokeObjectURL(objectURL);
resolve({
file,
duration: mySound.duration
});
},
false,
);
});  
}
$("#file").change(function(e) {
var files = Array.from(e.currentTarget.files);
Promise.all(files.map(computeLength)).then((songs) => {
console.log(songs);
});
});

最新更新