簡體   English   中英

在地圖函數中異步調用 API (React)

[英]Async call to API within map function (React)

所以我目前正在做一個項目,當用戶登陸儀表板頁面時,需要計算給定用戶的持有價值(股票列表及其數量)。 目前,我正在通過 GET 為持有列表中的每個項目調用 API,並計算這些股票的總當前價值。 最后,我得到了股票代碼、當前價值、數量和總額(數量 * 當前價值)。 然后我想通過 render() 中的 map 函數向用戶顯示這些值。

最初,我嘗試在 render 中的 map 函數中獲取和計算所有這些信息,該函數將迭代持有列表。 但是,我什至無法編譯它而不會遇到有關放置在 JSX 中的承諾的錯誤(我正在處理異步)。 我意識到我可以簡單地計算 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 中的每個值,但是當我運行它並且有館藏時,它不會記錄任何內容。 但是,如上所示,它確實記錄了列表(如果沒有迭代)。 有誰知道這里發生了什么? 我只是缺少一些小而基本的東西嗎?

謝謝你們!

編輯... (根據@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() 函數上調用 await。 (完全不認為你可以用 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 })

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM