Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/xpath/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 在创建多个HTMLAudioElement DOM元素时,有没有办法不冻结UI_Javascript_Web Audio Api - Fatal编程技术网

Javascript 在创建多个HTMLAudioElement DOM元素时,有没有办法不冻结UI

Javascript 在创建多个HTMLAudioElement DOM元素时,有没有办法不冻结UI,javascript,web-audio-api,Javascript,Web Audio Api,标题中的问题不言自明。我有这个网站,允许用户一次上传多个文件。然后它将遍历并检索每一个的持续时间 getDuration(file) { return new Promise(resolve => { let reader = new FileReader(); reader.onload = e => { let audio = new Audio(); audio.onloadeddata =

标题中的问题不言自明。我有这个网站,允许用户一次上传多个文件。然后它将遍历并检索每一个的持续时间

getDuration(file) {
    return new Promise(resolve => {
        let reader = new FileReader();
        reader.onload = e => {
            let audio = new Audio();
            audio.onloadeddata = () => {
                this.duration = audio.duration;
                resolve();
            };
            audio.src = e.target.result;
        };
        reader.readAsDataURL(file);
    });
}

但是,至少在Chrome中,当用户界面进行所有处理时,它会非常糟糕地冻结用户界面。我是否可以避免这种情况,或者以不同的方式处理这种情况?

您可以先不使用
文件读取器和data://uri

FileReader会将磁盘中的所有文件读取到内存中,其中包含大量文件,即大量IO,您的磁盘(HDD或SSD)将不喜欢它

然后从该文件创建data://URL不是免费操作,因此需要一些CPU时间。
最后,浏览器必须将该数据解码回原始二进制文件的URL,然后才能尝试将该数据解码为音频。这里再次出现了一些不必要的步骤,浪费了大量内存

相反,您可以简单地从用户发送的文件中创建一个blob://URL,并将
的src设置为该文件。这将是一个指向磁盘上实际文件的简单指针,因此浏览器将能够对其进行流式解码,并只在内存中追加所需的数据块

要创建这样一个blob://URL,必须使用
URL.createobejctur()
方法

请注意,即使对于来自磁盘的文件来说,这并不是那么重要,但您应该养成在使用此类blob://URL后撤消此类blob://URL的好习惯,因为它们会阻止文件被垃圾收集

函数getDuration(文件){ 返回新承诺(解决=>{ const audio=新音频(); audio.onloadedmetadata=()=>{ revokeObjectURL(文件) 解析(音频、持续时间); }; audio.src=URL.createObjectURL(文件); }); } document.querySelector(“输入”).oninput=async(evt)=>{ log(等待getDuration(evt.target.files[0]); }