首页 > 解决方案 > 循环中的循环总增量,但之后打印时返回 0

问题描述

我正在创建一个充当股票投资组合经理的 Alexa 应用程序。我有一个功能,它首先检索所有股票和属于用户的股票数量。对于这些股票中的每一个,我必须使用 axios 查询 API 以获取股票的价值,这意味着 axios get 语句嵌套在 forEach 循环中。然后我有一个 totalPrice 变量,它使用股票的总价格递增;这是通过将价格乘以拥有的股票数量 x 得出的

在 forEach 循环结束时,我想打印总价格,这将是投资组合的全部价值

当我在请求语句中打印出 totalPrice 时,它​​正确地添加了以前的总股票价格,但如果我在 forEach 循环之后打印 totalPrice,它会打印 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}`);

令我困惑的是,虽然数据是异步的,但我认为 using.then会等到数据被检索到。这似乎是这种情况,因为在 forEach 循环中打印总数时这是有效的。其他有趣的是,在控制台中,“总计为:0”首先打印。

标签: javascriptloopspromiseaxios

解决方案


最后的 console.log 打印 0 因为它是在你的 Promise 启动后立即执行的(但尚未完成)。

为了等到所有的承诺都完成,那么你可以:

  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 将一个 Promise 的返回值列表传递给它的 'then' 函数。因此,我们可以将 returnValues 参数的元素相加来计算总计。


推荐阅读