React Axios API 调用数组循环给出错误的顺序?

React Axios API call with array loop giving wrong order?

我正在学习 React 并使用数组进行一些 axios api 调用。我做了一个通过coinmarketcap收集数据的代码api来学习。

因此,我的意图是使用硬编码的加密货币 ID 数组从 api 获取价格,并将它们推入价格数组。但是我 运行 遇到了价格数组的问题,因为价格都乱七八糟。我应该按这个顺序得到一个数组

[比特币价格、ethereumprice、stellarprice、rippleprice]

但是当我在浏览器中 运行 时,价格 运行 不按此顺序显示,有时我收到订单,有时却没有。我使用了一个 onClick 调用 getPrice 方法的按钮。有谁知道我的代码出了什么问题?谢谢!

constructor(){
    super();

    this.state = {
        cryptos:["bitcoin","ethereum","stellar","ripple"],
        prices:[]
    };

    this.getPrice = this.getPrice.bind(this);

}


getPrice(){
    const cryptos = this.state.cryptos;
    console.log(cryptos);

    for (var i = 0; i < cryptos.length; i++){       
        const cryptoUrl = 'https://api.coinmarketcap.com/v1/ticker/' + cryptos[i];

    axios.get(cryptoUrl)
        .then((response) => {
            const data = response.data[0];
            console.log(data.price_usd);

            this.state.prices.push(data.price_usd);
            console.log(this.state.prices);
        })

        .catch((error) => {
        console.log(error);
        }); 
    }

}

如果你想按照异步调用的顺序接收数据,你可以使用Promise.all,它会等到数组的所有承诺都被执行并被解析,返回值他们被执行的顺序。

const cryptos = ['bitcoin', 'ethereum', 'stellar', 'ripple'];
const arr = [];
for (var i = 0; i < cryptos.length; i++){       
    const cryptoUrl = 'https://api.coinmarketcap.com/v1/ticker/' + cryptos[i];
    arr.push(axios.get(cryptoUrl));
}

Promise.all(arr).then((response) =>
  response.map(res => console.log(res.data[0].name, res.data[0].price_usd))
).catch((err) => console.log(err));

您可以在 for 循环中使用闭包来捕获 i 的值,并在数据返回后将其用作索引,而不是使用 push:

getPrice(){
    const cryptos = this.state.cryptos;
    console.log(cryptos);

    for (var i = 0; i < cryptos.length; i++) {
        const cryptoUrl = 'https://api.coinmarketcap.com/v1/ticker/' + cryptos[i];
        (function (x) {
            axios.get(cryptoUrl)
                .then((response) => {
                    const data = response.data[0];
                    console.log(data.price_usd);

                    var newPrices = this.state.prices;
                    newPrices[x] = data.price_usd;
                    this.setState({prices: newPrices}); 
                    console.log(this.state.prices);
                })
                .catch((error) => {
                    console.log(error);
                });
        })(i);
    }
}