映射函数内对API的异步调用(反应)

时间:2020-02-27 15:47:05

标签: javascript reactjs asynchronous

因此,我目前正在从事一个项目,当用户登陆仪表板页面时,需要计算给定用户的持股价值(股票清单及其数量)。目前,我正在通过GET为库存列表中的每个项目调用API,并计算这些库存的当前总值。最后,我给出了股票报价器,当前值,金额和总计(金额*当前值)。然后,我想通过render()中的map函数向用户显示这些值。

最初,我尝试在render内的地图函数中获取并计算所有这些信息,这些信息会在馆藏列表上进行迭代。但是,我什至无法编译它,而不会遇到关于将承诺放入JSX的错误(我正在处理异步)。我意识到我可以简单地在componentDidMount()中计算列表,所以我选择了这一点。

不幸的是,尽管这次确实可以编译,但我仍然看到问题。在componentDidMount()中,执行以下操作:

<div id="sizeobserver">Resize me!</div>

这是我在渲染功能中所做的

const holdings = store.getState().mainApp.portfolio.holdings;
var newHoldings = []
holdings.forEach(async element => {
  const stock = await axios.get(`https://api.iextrading.com/1.0/tops/last?symbols=${element.ticker}`);      
  let stockPrice = stock.data[0].price      
  let total = +stockPrice * +element.qty;
  newHoldings.push({
    ticker: element.ticker,
    qty: element.qty,
    price: stockPrice,
    totPrice: total
  })
});

this.setState({ activePortfolio: newHoldings })

当前,map函数仅将每个值记录在activePortfolio中,但是当我运行它并拥有馆藏时,它不记录任何内容。但是,如上所示,它确实记录了列表(如果未迭代)。有人知道这是怎么回事吗?我只是缺少一些小而基本的东西吗?

谢谢大家!

编辑... (根据@ zero298的评论)

{this.state.activePortfolio ? 
  // CONSOLE LOG HERE OF activePortfolio RETURNS THE CALCULATED LIST
  this.state.activePortfolio.map((value) => 
    // CONSOLE LOG HERE RETURNS NOTHING
    console.log(value)
    // <div>
    //   <p>{value.ticker} <span style={{right: '2vw', float: 'right'}}>{value.qty}x @ ${value.price}/ea</span></p>
    //   <p style={{float: 'right'}}> $ {value.totPrice}</p>
    // </div>
)
: 
  console.log("ERROR ACTIVE P")
}

因此,现在当我将新的馆藏设置为res时(顺便说一句,res在登录到那里时会正确显示数组值),仍然无法在render()的map函数中记录该值。我在这里做错什么了吗?我对诺言还是有点陌生​​。

编辑2 ... 好!因此,感谢@dave的帮助以及@ zero298。我最终使用了组合解决方案。上面编辑的唯一问题是我没有使componentDidMount()成为异步函数,也没有对Promise.all()函数调用await。 (完全不认为您可以使用componentDidMount()来做到这一点!)这是固定的解决方案...

    var promises = holdings.map(element => {
        return axios.get(`https://api.iextrading.com/1.0/tops/last?symbols=${element.ticker}`).then(stock => {
          let stockPrice = stock.data[0].price
          let total = +stockPrice * +element.qty;
          return ({
            ticker: element.ticker,
            qty: element.qty,
            price: stockPrice,
            totPrice: total
          });
        })
    })

    console.log(Promise.all(promises))
    Promise.all(promises).then(res => {
      newHoldings = res;
    });

非常感谢你们,我非常感谢您的帮助!

1 个答案:

答案 0 :(得分:1)

我认为您可能只想这样做:

await Promise.all(promises).then(res => {
  newHoldings = res;
});

如果这不起作用,您可以这样做:

for await (const holding of holdings) {
  const stock = await axios.get(`https://api.iextrading.com/1.0/tops/last?symbols=${holding.ticker}`);      
  let stockPrice = stock.data[0].price      
  let total = +stockPrice * +holding.qty;
  newHoldings.push({
    ticker: holding.ticker,
    qty: holding.qty,
    price: stockPrice,
    totPrice: total
  })
};

this.setState({ activePortfolio: newHoldings })