Home > Enterprise >  How to use await and async during axios API calls
How to use await and async during axios API calls

Time:04-06

const axios = require('axios');


const getShipmentDetails = ((nextCall) => {

        const res = axios({
            method: 'post',
            url: nextCall,
            headers:{ Authorization: "<Generated Bearer Token>"},
            data:{
                "filter" : {
                    "type" : "postDispatch",
                    "states" : ["SHIPPED"],
                    "orderDate" : {
                        "from" : "2022-04-01",
                        "to" : "2022-04-04"
                    }
                }
            }
        })

        if(res['data']['hasMore'] == false ){
            return res['data']['shipments'].concat(getShipmentDetails(res['data']['nextPageUrl']))
        }
        else{return res['data']['shipments']}

});

const result = getShipmentDetails("https://api.flipkart.net/sellers/v3/shipments/filter/");
console.log(result);

I am Recursively fetching data from paginated API. I am getting multiple errors while adding await/async functions in this code. Due to delay from the API calls output is printing "Undefined". Please update this code with await/async or any suitable method so that data from all the pages is concatenated.

CodePudding user response:

Acording to the axios docs, the axios method returns a promise, so all you have to do is add some async/await statements in the appropriate places: async on the getShipmentDetails function, and await for when its called, and an await on axios.

const axios = require('axios');
const SHIPMENT_AXIOS_CONFIG = { // Pulled this out for readability
    method: 'post',
    headers: { Authorization: '<Generated Bearer Token>'},
    data: {
        filter: {
            type: 'postDispatch',
            states: ['SHIPPED'],
            orderDate: {
                from: '2022-04-01',
                to: '2022-04-04',
            }
        }
    }
};
const getShipmentDetails = async (nextCall) => {
    const res = await axios({ // Wait for the response
        ...SHIPMENT_AXIOS_CONFIG,
        url: nextCall,
    });
    const { data } = res; // destructuring to get common properties makes the code more readable
    if (data.hasMore == false) { // Should this be hasMore === true?
        // Wait for the additional details
        const shipments = await getShipmentDetails(data.nextPageUrl);
        return data.shipments.concat(shipments);
    }
    return data.shipments;
};

const result = await getShipmentDetails('https://api.flipkart.net/sellers/v3/shipments/filter/');

CodePudding user response:

const axios = require('axios')


const getShipmentDetails = async ((url) => {

        const res = await axios({
            method: 'post',
            url: url,
            headers: { Authorization: "<Generated Bearer Token>"},
            data: {
                "filter" : {
                    "type" : "postDispatch",
                    "states" : ["SHIPPED"],
                    "orderDate" : {
                        "from" : "2022-04-01",
                        "to" : "2022-04-04"
                    }
                }
            }
        })

        if (res['data']['hasMore'] == true) {
            const more = await getShipmentDetails(res['data']['nextPageUrl'])
            return res['data']['shipments'].concat(more);
        }
        else {
            return res['data']['shipments']
        }
})

getShipmentDetails("https://api.flipkart.net/sellers/v3/shipments/filter/")
.then(result => console.log(result))

Should do what you want. I made the assumption that you got your hasMore conditional backwards since logically, you'd expect hasMore to be true if there were additional pages.

A note about async/await and promises:

If you use promises you have to use promises all the way down. Javascript doesn't offer a mechanism for blocking on a promise. So if you've got async code your only options are .then and async/await, which is syntactic sugar for .then. This is different from how Promises (or the equivalent) work in many other languages, including C# and Java.

Finally a few stylistic things: Javascript conventional style always puts a space between if and the parens around the conditional expression and a space between the conditional expression and block start. It's also convention to put a space between an object key and its value. And while both semi-colon and no-semicolon are common conventions, you should be consistent, using semicolons everywhere or nowhere

CodePudding user response:

Maybe a simpler approach would be by using do-while loop, something like this:

const axios = require('axios');

const callShipmentDetails = async (nextCall) => {
    const res = await axios({...})
    return res
}

const getShipmentDetails = ((url = "https://api.flipkart.net/sellers/v3/shipments/filter/") => {
    var hasMore = false
    // var times = 0
    do {
        var response = callShipmentDetails(url)
        hasMore = response.data.hasMore
        url = url.concat(response.data.nextPageUrl)
        /*
        this code is for breaking after 100 times if this becomes endless loop
        */
    //      times
    //    if (times > 100) break;
    } while (hasMore)
});
  • Related