javascript - 音频对象持续时间不断变化?
问题描述
我正在尝试获取列表中每个对象的持续时间(以秒为单位),但我的结果遇到了一些问题。我认为这是因为我没有完全理解异步行为。
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);
}
});
解决方案
像这样的东西应该可以在没有混乱的闭包的情况下工作,并且由于promises而增加了干净的异步性。
基本上,我们声明了一个辅助函数 ,computeLength
它采用 HTML5File
并执行您已经做过的魔法来计算它的长度。(虽然我确实添加了URL.revokeObjectURL
调用以避免内存泄漏。)
然而,promise 不只是返回持续时间,而是使用包含原始文件对象和计算的持续时间的对象来解析。
然后在事件处理程序中,我们映射files
选定的以从中创建computeLength
承诺,并使用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);
});
});
推荐阅读
- python - 使用 sed 或通过匹配多行来编辑 xml 文件
- python - 2 FlaskForm 中的日期选择器
- python - 熊猫:另一个列元素的条件滚动窗口?
- nginx - 使用 Ingress-NGINX 的 ExternalName 服务的 308 重定向循环
- django - 为什么它显示“类型对象'CourseInstructor'没有属性'对象'”
- c# - 为什么 NetworkStream.ReadAsync 没有超时?
- django - 无法在 Django 中使用模板标记在 for 循环中显示带有子表的父表
- python-3.x - discord.py 从 name#discriminator 获取成员实例
- r - R在PlotOnStaticMap上绘制多个轨道
- c - Mingw GCC 链接器在使用 std 选项标志时抱怨