Для общего увеличения цикла в цикле, но при последующей печати возвращает 0 - PullRequest
0 голосов
/ 05 февраля 2019

Я создаю приложение Alexa, которое выполняет функции менеджера портфеля акций.У меня есть функция, которая сначала извлекает все акции и количество акций, принадлежащих пользователю.Для каждой из этих акций я должен запросить API, используя axios, чтобы получить значение акции, то есть оператор get axios вложен в цикл forEach.Затем у меня есть переменная totalPrice, которая увеличивается с использованием общей цены акции;который определяется путем умножения цены на количество акций х, находящихся в собственности

. В конце цикла forEach я хочу напечатать totalPrice, который будет представлять собой целое значение портфеля

Когда яраспечатайте totalPrice в запросе, он корректно добавляет предыдущие итоговые цены акций, но если я напечатаю totalPrice после цикла forEach, он напечатает 0

var grandTotal = 0;
data.Items.forEach(function(element,index,array) {  
   var stock = element.Stock;
   var number = element.Number;
   var url = `www.api.com/${stock}`;

   const getDataValues = async url => {
     try {
      const response = await axios.get(url);
      const data = response.data;
      var Price = data.PRICE;
      return Price;
    } catch (error) {
      console.log(error);
    }
  };

 let promiseObject = getDataValues(url);
 promiseObject.then(function(result) {
     var totalPriceofStocks = result * amount;
     grandTotal += totalPriceOfStocks;
     console.log(`{grandTotal}`);        // This bit accumulates correctly
 });
});
console.log(`The grand total is: ${grandTotal}`);

, что меня смущает, так как данные асинхронныеЯ думал, что использование .then будет ждать, пока данные не будут получены.Это похоже на случай, когда при печати итога в цикле forEach это работает.Что еще интересно, так это то, что в консоли сначала выводится «Итого: 0».

Ответы [ 2 ]

0 голосов
/ 05 февраля 2019

В конце console.log выводит 0, потому что он выполняется сразу после того, как ваши обещания инициированы (и еще не завершены).

Чтобы дождаться, пока все обещания не будут выполнены, вы можете:

  1. Сохранить обещания в списке
  2. Использовать Promise.all , который принимает список обещаний в качестве параметра и разрешает, когда все обещания разрешены (вваш случай, когда все запросы axios завершены).

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

const promises = []

const getDataValues = async url => {
  try {
    const response = await axios.get(url);
    const data = response.data;
    var Price = data.PRICE;
    return Price;
  } catch (error) {
    console.log(error);
  }
};

var grandTotal = 0;
data.Items.forEach(function(element,index,array) {  
  var stock = element.Stock;
  var number = element.Number;
  var url = `www.api.com/${stock}`;

  let promiseObject = getDataValues(url);
  promiseObject.then(function(result) {
    var totalPriceofStocks = result * amount;
    grandTotal += totalPriceOfStocks;
    console.log(`${grandTotal}`);        // This bit accumulates correctly
    return totalPriceOfStocks
  });
  promises.push(promiseObject)
});

Promise.all(promises)
  .then(function (resultValues) {
    console.log(`The grand total is: ${grandTotal}`);
    let resultSum = 0;
    resultValues.forEach(function (value) {
      resultSum += value;
    })
    console.log(`This is also the total: ${resultSum}`);
  })

Обратите также внимание, что я добавил возвращаемое значение к вашему объекту обещания.У меня есть это, чтобы показать альтернативный способ накопления общего итога, а не полагаться на глобальную ценность.Логика заключается в том, что когда Promise возвращает значение, это значение становится доступным для функции, передаваемой в цепочку функции then.В этом случае, когда мы используем Promise.all, Promise.all передает список возвращаемых значений обещания его функции then.Поэтому мы можем добавить элементы параметра returnValues ​​вместе, чтобы вычислить общий итог.

0 голосов
/ 05 февраля 2019

Используйте цикл for..of вместо forEach, в котором ожидание должно работать как положено

for (const element of data.Items) {
   var stock = element.Stock;
   var number = element.Number;
   var url = `www.api.com/${stock}`;

   const getDataValues = async url => {
     try {
      const response = await axios.get(url);
      const data = response.data;
      var Price = data.PRICE;
      return Price;
    } catch (error) {
      console.log(error);
    }
  };

 const result = await getDataValues(url);
 var totalPriceofStocks = result * amount;
 grandTotal += totalPriceOfStocks;
 console.log(`{grandTotal}`);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...