我正在开发一个简单的Web应用程序,该应用程序需要加载16个音频文件来处理听力测试。但是我的代码两次加载文件!
应用程序必须非常轻便,快速,所以这是一个大问题。
出于同样的原因,我不想使用jQuery库。
function loadSound(array) {
var i = 0;
array.forEach(function(soundUrl) {
var request = new XMLHttpRequest();
request.open('GET', soundUrl, true);
request.responseType = 'arraybuffer';
request.onloadend = function() {
var audioData = request.response;
contextAudio.decodeAudioData(audioData, function(buffer) {
sources[i] = contextAudio.createBufferSource();
sources[i].buffer = buffer;
sources[i].connect(contextAudio.destination);
i++
});
};
request.send(null);
});
}
soundList数组和loadSound调用:
var soundList = new Array(
'http://localhost/testauditif/sons/440L.wav',
'http://localhost/testauditif/sons/440R.wav',
'http://localhost/testauditif/sons/125L.wav',
'http://localhost/testauditif/sons/125R.wav',
'http://localhost/testauditif/sons/250L.wav',
'http://localhost/testauditif/sons/250R.wav',
'http://localhost/testauditif/sons/500L.wav',
'http://localhost/testauditif/sons/500R.wav',
'http://localhost/testauditif/sons/1000L.wav',
'http://localhost/testauditif/sons/1000R.wav',
'http://localhost/testauditif/sons/2000L.wav',
'http://localhost/testauditif/sons/2000R.wav',
'http://localhost/testauditif/sons/4000L.wav',
'http://localhost/testauditif/sons/4000R.wav',
'http://localhost/testauditif/sons/8000L.wav',
'http://localhost/testauditif/sons/8000R.wav'
);
loadSound(soundList);
javascript控制台: XHRGEThttp://localhost/testauditif/sons/440L.wav [HTTP / 1.1 200 OK 0ms]
XHRGEThttp://localhost/testauditif/sons/440R.wav
[HTTP/1.1 200 OK 0ms]
0 script.js:88:12
XHRGEThttp://localhost/testauditif/sons/125L.wav
[HTTP/1.1 200 OK 0ms]
XHRGEThttp://localhost/testauditif/sons/125R.wav
[HTTP/1.1 200 OK 0ms]
0 script.js:88:12
XHRGEThttp://localhost/testauditif/sons/250L.wav
[HTTP/1.1 200 OK 0ms]
XHRGEThttp://localhost/testauditif/sons/250R.wav
[HTTP/1.1 200 OK 0ms]
XHRGEThttp://localhost/testauditif/sons/500L.wav
[HTTP/1.1 200 OK 0ms]
XHRGEThttp://localhost/testauditif/sons/500R.wav
[HTTP/1.1 200 OK 0ms]
XHRGEThttp://localhost/testauditif/sons/1000L.wav
[HTTP/1.1 200 OK 0ms]
XHRGEThttp://localhost/testauditif/sons/1000R.wav
[HTTP/1.1 200 OK 0ms]
XHRGEThttp://localhost/testauditif/sons/2000L.wav
[HTTP/1.1 200 OK 0ms]
XHRGEThttp://localhost/testauditif/sons/2000R.wav
[HTTP/1.1 200 OK 0ms]
XHRGEThttp://localhost/testauditif/sons/4000L.wav
[HTTP/1.1 200 OK 0ms]
XHRGEThttp://localhost/testauditif/sons/4000R.wav
[HTTP/1.1 200 OK 0ms]
XHRGEThttp://localhost/testauditif/sons/8000L.wav
[HTTP/1.1 200 OK 0ms]
XHRGEThttp://localhost/testauditif/sons/8000R.wav
[HTTP/1.1 200 OK 0ms]
XHRGEThttp://localhost/testauditif/sons/440L.wav
[HTTP/1.1 200 OK 0ms]
XHRGEThttp://localhost/testauditif/sons/440R.wav
[HTTP/1.1 200 OK 0ms]
XHRGEThttp://localhost/testauditif/sons/125L.wav
[HTTP/1.1 200 OK 0ms]
XHRGEThttp://localhost/testauditif/sons/125R.wav
[HTTP/1.1 200 OK 0ms]
XHRGEThttp://localhost/testauditif/sons/250L.wav
[HTTP/1.1 200 OK 0ms]
XHRGEThttp://localhost/testauditif/sons/250R.wav
[HTTP/1.1 200 OK 0ms]
XHRGEThttp://localhost/testauditif/sons/500L.wav
[HTTP/1.1 200 OK 0ms]
XHRGEThttp://localhost/testauditif/sons/500R.wav
[HTTP/1.1 200 OK 0ms]
XHRGEThttp://localhost/testauditif/sons/1000L.wav
[HTTP/1.1 200 OK 0ms]
XHRGEThttp://localhost/testauditif/sons/1000R.wav
[HTTP/1.1 200 OK 0ms]
XHRGEThttp://localhost/testauditif/sons/2000L.wav
[HTTP/1.1 200 OK 0ms]
XHRGEThttp://localhost/testauditif/sons/2000R.wav
[HTTP/1.1 200 OK 0ms]
XHRGEThttp://localhost/testauditif/sons/4000L.wav
[HTTP/1.1 200 OK 0ms]
XHRGEThttp://localhost/testauditif/sons/4000R.wav
[HTTP/1.1 200 OK 0ms]
XHRGEThttp://localhost/testauditif/sons/8000L.wav
[HTTP/1.1 200 OK 0ms]
XHRGEThttp://localhost/testauditif/sons/8000R.wav
[HTTP/1.1 200 OK 0ms]
答案 0 :(得分:1)
关闭!!!
让我们来看看代码发生了什么。
您开始遍历数组,每个URL在soundUrl
中定义为array.forEach(function(soundUrl) {})
。请注意,变量i
保留在该匿名函数中,因为它是在loadSound
函数中定义的。
您使用request.send(null);
发送请求。在request.onloadend
函数中,i
的值为0。到目前为止一切正常。
现在麻烦了。在不等待调用onloadend
的情况下,您移至forEach循环中的下一个soundUrl
。初始化request.onloadend
时,除非已经调用了先前请求的i
,否则onloadend
的值仍为0。 (假设音频文件需要花费一些时间才能下载到浏览器,则这种可能性很小)
在forEach循环的中间某处,您的第一个请求request.onloadend
递增时会调用i
。
最终结果?最后,您在sources
数组中出现了堆垃圾,其中下载了很少的文件,几乎没有一个文件被下一个音频文件覆盖,并且它们之间有空洞。
PS:如代码所示,它不起作用。那是真正的问题吗?也许。没有有关array
包含的内容以及代码发送到后端的请求数量的进一步信息。
我建议的解决方案。
function loadSound(array) {
array.forEach(function(soundUrl, i) {
// No need to declare var i for iteration. Foreach provides the index.
var request = new XMLHttpRequest();
// Creating an instance of XMLHttpRequest inside loop to ensure
// request.onloadend does not get overriden in the next iteration.
request.open('GET', soundUrl, true);
request.responseType = 'arraybuffer';
request.onloadend = function() {
// Retain i inside the function using a local variable inside the callback function.
var idx = i;
var audioData = request.response;
contextAudio.decodeAudioData(audioData, function(buffer) {
// Not sure whether decodeAudioData in asyc. If so, you again need to retain idx inside the callback.
var src_idx = idx;
sources[src_idx] = contextAudio.createBufferSource();
sources[src_idx].buffer = buffer;
sources[src_idx].connect(contextAudio.destination);
});
};
request.send(null);
});
}
答案 1 :(得分:0)
请尝试是否可以解决您的问题
此版本未使用var i
设置源中的内容。如果以后需要i
来知道已经缓冲了多少源。只需将i
的长度设为sources
。
const request = new XMLHttpRequest();
var sources = null;
var i = null; // only if you want to keep i
function loadSound(array) {
console.log(array); // only here for testing
var sources = []; // define or re-define sources as empty array
array.forEach(function(soundUrl) {
request.open('GET', soundUrl, true);
request.responseType = 'arraybuffer';
request.onloadend = function() {
console.log(request); // only here for testing
var audioData = request.response;
contextAudio.decodeAudioData(audioData, function(buffer) {
let newsource = contextAudio.createBufferSource();
// let is ES6 style it can also work without let
newsource.buffer = buffer;
newsource.connect(contextAudio.destination);
sources.push(newsource);
// added your new source to your sources array
var i = sources.length;
// if you need var i elsewhere it now contains total number of sources
// if you don't need var i hereafter remove it from the code
console.log(sources); // only here for testing
});
};
request.send(null);
});
}