I'm learing WebAudio API. I'm facing a problem with it. Basically things are asynchronous here...so im getting a bit confused. Please help.Here is my code:-
//"use strict";
var sources = new Array();
var actx;
var songs = ['src1.mp3', 'src2.mp3'];
async function start() {
console.log("WELCOME!!");
try {
actx = new AudioContext();
} catch (e) {
console.log('WebAudio api is not supported!!');
}
await getBuffers(actx, songs);
console.log(sources);
console.log(sources.length);
}
function load_song(url) {
let promise = new Promise((resolve, reject) => {
let request = new XMLHttpRequest();
request.open('GET', url, true);
request.responseType = 'arraybuffer';
request.onload = () => {
let audioData = request.response;
resolve(audioData);
}
request.onerror = () => {
reject(new error("Could not load the song:- " + url));
}
request.send();
});
return promise;
}
//creats buffers
async function getBuffers(actx, songs) {
// let buffer_list = new Array();
for (let x = 0; x < songs.length; x++) {
let temp = actx.createBufferSource();
await load_song(songs[x]).then((audioData) => {
actx.decodeAudioData(audioData).then((decodedAudioData) => {
temp.buffer = decodedAudioData;
sources.push(temp);
}).catch((error) => {
console.error(error);
});
});
}
//console.log(buffers.length);
}
async function play() {
//start();
sources[0].start(0);
//sources[1].start(0);
}
function stop() {
sources[0].stop(0);
//sources[1].stop(0);
}
Here in the two lines console.log(sources)
and console.log(sources.length)
. Here the results are. Why console.log(sources.length)
is 0?
Please help me........Thank you.
You need to return
actx.decodeAudioData(audioData).then((decodedAudioData) => {
As you are not returning it, you dont await
it. Therefore the log appears before the array gets filled, however console.log(sources)
is live, so you see the latest change.
Such mistakes are more unlikely to happen when you use await
everywhere, and thats also easier to read IMO:
async function getBuffers(actx, songs) {
const sources = []; //mutating a global variable isnt good, so lets make it local
for (const song of songs) { //for...of is so beautiful, why dont you use it?
try { //this is similar to .catch
let temp = actx.createBufferSource();
const audioData = await load_song(song);
const decodedAudioData = await actx.decodeAudioData(audioData);
temp.buffer = decodedAudioData;
sources.push(temp);
} catch(e){ console.error(e); } //okay that does not count as an error handler...
}
return sources; //getBuffers implies that it returns sth
}