Async Javascript: ожидание обработки данных в цикле for перед переходом к новой функции - PullRequest
0 голосов
/ 06 мая 2018

У меня проблемы с пониманием того, как обойти асинхронное поведение Javascript в цикле forEach. Эта проблема довольно сложна (извините), но идея цикла следующая:

  • Цикл каждого элемента в массиве
  • Сделать HTTP-запрос из скрипта провайдера
  • Затем мне нужно умножить каждый элемент массива на постоянную
  • Назначение нового массива элементу в объекте
  • После цикла возьмите все массивы и сложите их в один массив

Данные будут присвоены массиву indvCoinPortfolioChartData

Я ищу любые недостатки в цикле событий. Я считаю, что битва делает эту задачу синхронной, проверяя, назначены ли мои данные перед агрегацией данных.

выпуск

Когда я добавляю все массивы вместе, ОДИН набор данных не суммируется (я думаю, потому что он все еще обрабатывается после вызова функции). Нет ошибки, но в ней нет всех данных о монетах в окончательном агрегированном массиве.

Это проблема, которую я вижу в функции aggregatePortfolioChartData. Он начинает цикл for только с двумя элементами в массиве, а затем показывает 3. Третий элемент не был обработан до тех пор, пока не начался цикл for.

образ журнала консоли (записывается с помощью функции aggregatePortfolioChartData)

журнал отладки при успешной агрегации

var indivCoinPortfolioChartData = {'data': []};
for(var i = 0; i < this.storedCoins.Coins.length; i++)
{  
  let entry = this.storedCoins.Coins[i];
  localThis._data.getChart(entry.symbol, true).subscribe(res => {localThis.generateCoinWatchlistGraph(res, entry);});
  localThis._data.getChart(entry.symbol).subscribe(res => {
    if(entry.holdings > 0)
    {
      let data = res['Data'].map((a) => (a.close * entry.holdings));
      indivCoinPortfolioChartData.data.push({'coinData': data});
      localThis.loadedCoinData(loader, indivCoinPortfolioChartData);
    }
    else
    {
      localThis.loadedCoinData(loader, indivCoinPortfolioChartData);
    }
  });
}

Данные загруженной монеты

loadedCoinData(loader, indivCoinPortfolioChartData)
{
  this.coinsWithData++;
  if(this.coinsWithData === this.storedCoins.Coins.length - 1)  
  {
    loader.dismiss();
    this.aggregatePortfolioChartData(indivCoinPortfolioChartData);
  }
}

aggregatePortfolioChartData

aggregatePortfolioChartData(indivCoinPortfolioChartData)
{
  console.log(indivCoinPortfolioChartData);
  var aggregatedPortfolioData = [];
  if(indivCoinPortfolioChartData.data[0].coinData)
  {
    let dataProcessed = 0;
    for(var i = 0; i < indivCoinPortfolioChartData.data[0].coinData.length; i++)
    {
      for(var j = 0; j< indivCoinPortfolioChartData.data.length; j++)
      {
        let data = indivCoinPortfolioChartData.data[j].coinData[i];
        if(data)
        {
          aggregatedPortfolioData[i] = (aggregatedPortfolioData[i] ? aggregatedPortfolioData[i] : 0) + data;
          dataProcessed++;
        }
        else
        {
          dataProcessed++;
        }
      }
      if(dataProcessed === (indivCoinPortfolioChartData.data[0].coinData.length) * (indivCoinPortfolioChartData.data.length))
      {
        console.log(dataProcessed + " data points for portfolio chart");
        this.displayPortfolioChart(aggregatedPortfolioData);
      }
    }
  }
}

Спасибо за помощь в решении этой утомительной проблемы.

...