javascript - 在 map 函数中异步调用 API (React)

标签 javascript reactjs asynchronous

因此,我目前正在开发一个项目,当用户登陆仪表板页面时,需要计算给定用户的持仓值(value)(股票列表及其金额)。目前,我正在通过 GET 为持有列表中的每一项调用 API,并计算这些股票的当前总值(value)。最后,我得到了股票代码、当前值、金额和总计(金额 * 当前值)。然后我想通过 render() 中的 map 函数向用户显示这些值。

最初,我尝试在渲染中的 map 函数中获取并计算所有这些信息,该函数将迭代馆藏列表。然而,我什至无法让它编译而不遇到关于放置在 JSX 中的 promise 的错误(我正在处理异步)。我意识到我可以简单地计算 componentDidMount() 中的列表,所以我选择了这样做。

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

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 })

这是我在渲染函数中所做的事情

{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")
}

目前, map 函数仅记录 activePortfolio 中的每个值,但是当我运行它并且有 Assets 时,它不会记录任何内容。然而,如上所示,它确实记录了列表(如果没有迭代)。有谁知道这是怎么回事?我只是错过了一些小而基本的东西吗?

谢谢大家!

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

    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;
    });

所以现在,当我将新的持有设置到 res 时(顺便说一句,res 在记录时正确显示数组值),它仍然无法在 render() 内的 map 函数中记录该值。我在这里做错了什么吗?我对 Promise 还是有点陌生​​。

编辑 2... 好的!感谢@dave 和@zero298 的帮助。我最终使用了组合解决方案。上述编辑的唯一问题是我没有将 componentDidMount() 设为异步函数,也没有在 Promise.all() 函数上调用 wait 。 (完全没想到你可以用 componentDidMount() 做到这一点!)这是固定的解决方案......

async componentDidMount(){

    *... other init code ...*

    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))
    await Promise.all(promises).then(res => {
      newHoldings = res;
    });
};

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

最佳答案

我想你可能只想这样做:

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 })

关于javascript - 在 map 函数中异步调用 API (React),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60436930/

相关文章:

c# - 延迟然后执行任务

java - 在 Activity 之间传递 Future 对象

javascript - 在 D3 v4.0.0-alpha.40 中不使用 data().enter() 附加拖动行为

javascript - Mobx 状态树流程。如何知道何时完成?

javascript - Uncaught Error : A state mutation was detected between dispatches

c++ - boost::asio + std::future - 关闭套接字后访问冲突

javascript - 在 Javascript 中抓取表格元素

javascript - 单击时使用 javascript 添加多个文本阴影规则

javascript - 正则表达式捕获标签

html - 我正在尝试在新选项卡中打开此链接,这样用户就不必离开我的网站,但它不适用于 _blank