【问题标题】:Why array.length is not working while array is filled by a async function in javascript为什么 array.length 不起作用,而数组由 javascript 中的异步函数填充
【发布时间】:2018-07-01 09:34:09
【问题描述】:

我正在学习 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?
请帮帮我........谢谢。

【问题讨论】:

  • console.log(sources) 由于 chrome 的行为,当您在开发者控制台中展开它时会评估它,此时数组已被填充,但是当您记录长度时,数组尚未填充。
  • await load_song(songs[x]).then 你的混合 async/await 与 thenable 回调.. 尝试 const audioData = await load_song(songs[x])

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


【解决方案1】:

您应该将getBuffers 代码更改为类似的内容

async function getBuffers(actx, songs) {
    try {
        for (let song of songs) {
            let temp = actx.createBufferSource();
            var audioData = await load_song(songs[x])
            var decodedAudioData = await actx.decodeAudioData(audioData)
            temp.buffer = decodedAudioData;
            sources.push(temp);
        }
    } catch (e) { console.log(e) }
}

【讨论】:

    【解决方案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
    }
    

    【讨论】:

    • use await everywhere 我正要发布一个带有这个想法的答案.. :).. 我什至会说取出try / catch 因为这确实应该被允许传播,并且一些更高级别的错误处理会处理任何报告。哦,刚刚注意到您在catch 的末尾添加了评论。
    • @keith 同意。但我想尽可能接近 OPs 代码。我已经改变了很多,我不想压倒他。
    • @Jonas W. actx.decodeAudioData() 不是需要三个参数吗?和 sources[] 我已将其全局用于调试目的...
    • 顺便说一句 @Jonas W. 什么是 IMO??
    • @uzumaki 1) 我不知道,这取自您的代码。 2)好吧,那是可能的。如果他在生产中改变 3) 在我看来 4) 不,我不是,请查看await docs....
    猜你喜欢
    • 1970-01-01
    • 2015-10-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-28
    相关资源
    最近更新 更多