简体   繁体   中英

Awaiting Multiple Axios Calls before Dispatching Action in React Redux

I have a React Redux app that needs to call multiple API endpoints using axios , await the results from these API calls, then dispatch an action.

Problem: In my current implementation below, it appears that the action is being dispatched by redux-thunk before the API call results are returned by axios .

How can we fix the problem so that we wait for all 3 results to be returned from the 3 axios calls, before dispatching the action?

/src/actions/index.js

const axios = require('axios');
import { GET_PRICES } from './types';

export function getSpotPrice(crypto) {
    axios.get(`https://api.coinbase.com/v2/prices/${crypto}-USD/spot`).then( (response) => {
        return parseFloat(response.data.data.amount);
    }).catch((err) => {
        console.log(err)
    })
}

function timeout(ms) {
    return new Promise(resolve => setTimeout(resolve, ms));
}

export function getSpotPrices() {
    return function(dispatch) {
        const cryptoList = ['BTC', 'ETH', 'XRP'];
        let cryptoRates = {}

        cryptoList.forEach(async (crypto, i) => {
            await timeout(1000);        // Wait 1 sec between API calls
            cryptoRates[crypto] = await getSpotPrice(crypto);
        });

        dispatch({
            type: GET_PRICES,
            payload: cryptoRates,
        })
        console.log('cryptoRates:', cryptoRates)        // returns {}
    }
}

You need to make the containing function async await all of your async calls before dispatching, like so:

export function getSpotPrices() {
    return async function(dispatch) {
        const cryptoList = ['BTC', 'ETH', 'XRP'];
        let cryptoRates = {}

        for(let crypto of cryptoList) {
            await timeout(1000);        // Wait 1 sec between API calls
            cryptoRates[crypto] = await getSpotPrice(crypto);
        }

        dispatch({
            type: GET_PRICES,
            payload: cryptoRates,
        });
        console.log('cryptoRates:', cryptoRates);
    }
}

Another way I believe you can do this is with the Promise.all method. When all the promises in an array have resolved, it's then statement is called.

var promise1 = Promise.resolve(3);
var promise2 = 42;
var promise3 = new Promise(function(resolve, reject) {
  setTimeout(resolve, 100, 'foo');
});

Promise.all([promise1, promise2, promise3]).then(function(values) {
  console.log(values);
});

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM