为什么array.length在javascript中由异步函数填充数组时不起作用

时间:2018-01-22 17:15:26

标签: javascript arrays async-await es6-promise web-audio

我正在学习WebAudio API。我遇到了问题。基本上这里的东西是异步的...所以我有点困惑。请帮忙。这是我的代码: -

//"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);
}

这两行console.log(sources)console.log(sources.length)。结果如下。为什么console.log(sources.length)为0? 请帮帮我........谢谢。

in web colsole here is the result.

2 个答案:

答案 0 :(得分:2)

您需要返回

actx.decodeAudioData(audioData).then((decodedAudioData) => {

当你没有归还它时,你不会await它。因此,日志会在数组填充之前显示,但是console.log(sources)处于活动状态,因此您会看到最新的更改。

当您在任何地方使用await时,更不可能发生此类错误,这也更容易阅读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
}

答案 1 :(得分:1)

您应该为此类

更改input[name="myname"]{ } input[type="text"]{ } input[value=""]{ } input[title="First Name"]{ } input[placeholder="First Name *"]{ } 代码
getBuffers