Rawland Hustle
Rawland Hustle

Reputation: 781

Merging two arrays from chained axios requests

I am chaining a bunch of axios get request to different endpoints of an API and I'm trying to create an array like this from the data (simplified):

[
    {
        name: "John",
        id: 1,
        gender: "male"
    },
    {
        name: "Anna",
        id: 2,
        gender: "female"
    },
]

In one of the requests I retrieve each person's name and id in an array like this:

[
    {
        name: "John",
        id: 1
    },
    {
        name: "Anna",
        id: 2
    },
]

Now I only need to get their gender by sending each persons's id in two separate requests to an endpoint.

I have spent hours trying to construct the array at the top with push() and then() but I just can't get it right.

How do I go about this?

I'm chaining the axios requests like this btw:

axios.get('api/' + endpoint1]).then(response => {
    axios.get('api/' + endpoint2).then(response => {
        axios.get('api/' + endpoint3).then(response => {
            // and so on...
         });
    });
});

UPDATE 1:

I feel like I didn't explain the problem properly. This is what my code looks like right now, starting from the last promise. How can I change it in order to get the array at the top of my question?

.then(response => {

    people= response.data; // Array of people including their name id (not their gender though)

    for (var key in people) {

        var person = {};

        person["name"] = people[key].node.name;

        person["id"] = people[key].node.id;

        finalArray.push(person);

        axios.get('api/' + endpoint3, { // Endpoint for getting a persons gender from id
            params: {
                personId: person.id
                }
        }).then(response => {

            // I don't know what to do here...            

        });

    }

    console.log(finalArray); // Gives me an array of objects without "gender".

});

UPDATE 2:

Thanks alot for your answers!

I've combined some of your solutions and this is how my real code looks right now. The requests to http://api.ntjp.se/coop/api/v1/serviceProducers.json are not sent. Why?

I also don't want to keep the whole objects within the cooperations response array before calling http://api.ntjp.se/coop/api/v1/serviceProducers.json. I just want to save two specific key/value pairs from each object. These two key/value pairs are both within an object called "serviceContract" within in each response object. How do I save them?

<html>

<head>
    <script src="https://unpkg.com/axios/dist/axios.min.js"></script>
</head>

<body>

    <script>

        getConnectionStatusData();

        async function getConnectionStatusData() {

            let serviceDomains = await axios.get('http://api.ntjp.se/coop/api/v1/serviceDomains.json', {
                                        params: {
                                            namespace: "crm:scheduling"
                                        }
                                    });

            serviceDomainId = serviceDomains.data[0].id;

            let connectionPoints = await axios.get('http://api.ntjp.se/coop/api/v1/connectionPoints.json', {
                                        params: {
                                            platform: "NTJP",
                                            environment: "PROD"
                                        }
                                    });

            connectionPointId = connectionPoints.data[0].id;

            let logicalAddresss = await axios.get('http://api.ntjp.se/coop/api/v1/logicalAddresss.json', {
                                        params: {
                                            logicalAdress: "SE2321000016-167N",
                                            serviceConsumerHSAId: "SE2321000016-92V4",
                                            connectionPointId: connectionPointId
                                        }
                                    });

            logicalAddressId = logicalAddresss.data[0].id;

            let serviceConsumers = await axios.get('http://api.ntjp.se/coop/api/v1/serviceConsumers.json', {
                                        params: {
                                            connectionPointId: connectionPointId,
                                            logicalAddressId: logicalAddressId
                                        }
                                    });

            consumer = serviceConsumers.data.filter(obj => {
                  return obj.hsaId === "SE2321000016-92V4"
                });

            serviceConsumerId = consumer[0].id;

            let cooperations = await axios.get('http://api.ntjp.se/coop/api/v1/cooperations.json', {
                                        params: {
                                            connectionPointId: connectionPointId,
                                            logicalAddressId: logicalAddressId,
                                            serviceDomainId: serviceDomainId,
                                            serviceConsumerId: serviceConsumerId,
                                            include: "serviceContract"
                                        }
                                    });

            for(var idx in cooperations.data) {

                var data = async () => { return await axios.get('http://api.ntjp.se/coop/api/v1/serviceProducers.json', {
                                        params: {
                                            connectionPointId: connectionPointId,
                                            logicalAddressId: logicalAddressId,
                                            serviceDomainId: serviceDomainId,
                                            serviceConsumerId: serviceConsumerId,
                                            serviceContractId: cooperations.data[idx].serviceContract.id
                                        }
                                    }) }
                cooperations.data[idx].producerDescription = data.description;
                cooperations.data[idx].producerHSAId = data.hsaId;
            }

            console.log(cooperations.data);

        }

    </script>

</body>

UPDATE 3

I finally made it work but why do I have to reference to the data like response.data[0].description when I push it into finalResult in the end? I mean, why doesn't just response.data.description work, as it does for @Cold Cerberus?

Other than that, is my code ok in or have I done something wrong?

Thanks guys!

<html>

<head>
    <script src="https://unpkg.com/axios/dist/axios.min.js"></script>
</head>

<body>

    <script>

        getConnectionStatusData();

        async function getConnectionStatusData() {

            let serviceDomains = await axios.get('http://api.ntjp.se/coop/api/v1/serviceDomains.json', {
                                        params: {
                                            namespace: "crm:scheduling"
                                        }
                                    });

            serviceDomainId = serviceDomains.data[0].id;

            let connectionPoints = await axios.get('http://api.ntjp.se/coop/api/v1/connectionPoints.json', {
                                        params: {
                                            platform: "NTJP",
                                            environment: "PROD"
                                        }
                                    });

            connectionPointId = connectionPoints.data[0].id;

            let logicalAddresss = await axios.get('http://api.ntjp.se/coop/api/v1/logicalAddresss.json', {
                                        params: {
                                            logicalAdress: "SE2321000016-167N",
                                            serviceConsumerHSAId: "SE2321000016-92V4",
                                            connectionPointId: connectionPointId
                                        }
                                    });

            logicalAddressId = logicalAddresss.data[0].id;

            let serviceConsumers = await axios.get('http://api.ntjp.se/coop/api/v1/serviceConsumers.json', {
                                        params: {
                                            connectionPointId: connectionPointId,
                                            logicalAddressId: logicalAddressId
                                        }
                                    });

            consumer = serviceConsumers.data.filter(obj => {
                  return obj.hsaId === "SE2321000016-92V4"
                });

            serviceConsumerId = consumer[0].id;

            let cooperations = await axios.get('http://api.ntjp.se/coop/api/v1/cooperations.json', {
                                        params: {
                                            connectionPointId: connectionPointId,
                                            logicalAddressId: logicalAddressId,
                                            serviceDomainId: serviceDomainId,
                                            serviceConsumerId: serviceConsumerId,
                                            include: "serviceContract"
                                        }
                                    });

            var finalData = [];

            cooperations.data.forEach(function(cooperation) {

                axios.get('http://api.ntjp.se/coop/api/v1/serviceProducers.json', {
                            params: {
                                connectionPointId: connectionPointId,
                                logicalAddressId: logicalAddressId,
                                serviceDomainId: serviceDomainId,
                                serviceConsumerId: serviceConsumerId,
                                serviceContractId: cooperation.serviceContract.id
                            }
                }).then(response => {
                finalData.push({serviceContract: cooperation.serviceContract.namespace, serviceProducerDescription: response.data[0].description, serviceProducerHSAId: response.data[0].hsaId});
            });


            });

            console.log(finalData);



        }

    </script>

</body>

Upvotes: 1

Views: 3169

Answers (3)

Alex Pappas
Alex Pappas

Reputation: 2658

I'm not quite sure of your specific problem. But assuming that what you mean is you have two endpoints, first is the one that returns an array of object (lets call it 'getPeopleArray'):

[
 {
    name: "John",
    id: 1
 },
 {
    name: "Anna",
    id: 2
 }
]

and second endpoint returns the gender of the given id (lets call it 'getGender' with one param id), .push will not do the job for you.

Your problem can be solved with something like this:

let peopleArray = [];
axios.get('api/' + 'getPeopleArray').then(people => {
    peopleArray = people;
    people.forEach((person, index) => {
       axios.get('api/' + 'getGender?id='.concat(person.id.toString()))
           .then(gender => {
               peopleArray[index].gender = gender;
           });
    });
});

First is you save the returned array of your first request and then you will have to loop through each object in that array to get and assign their genders from your second endpoint using the index argument of your [].forEach(callbackfn). As long as there is no manipulation with peopleArray during or before all requests are finished, the index will be correct.

Update 2: In response to your question in the comments "why .push doesn't work?", I decided to make another approach If you want to end your algorithm with using .push and go without tracking indexes.

let peopleArray = [];
axios.get('api/' + 'getPeopleArray').then(people => {
    people.forEach((person) => {
       axios.get('api/' + 'getGender?id='.concat(person.id.toString()))
           .then(gender => {
               peopleArray.push({id: person.id, name: person.name, gender, gender});
           });
    });
});

This way you will only push your object to your collection peopleArray when its respective gender is also fetched. This will also eliminate having to use .map (as suggested in the comments) for storing only the individual object's properties you desire to keep since you pushed a new structured object on line peopleArray.push({id: person.id, name: person.name, gender, gender});.

Upvotes: 1

デビット
デビット

Reputation: 289

You can use async/awaits and reassign gender key to first endpoint data ...

var users;
axios.get('api/' + endpoint1]).then(response => {
   users = response; // assume all user id list
   for(var idx in users) {
     var data = async () => { return await axios.get('api/' + users[idx].id) } //get gender api by user id
     users[idx].gender = data.gender; //create gender key value 
   }
   console.log(users);
});

Upvotes: 0

Alberti Buonarroti
Alberti Buonarroti

Reputation: 459

I do not like to read chained promises and prefer to use async/await instead. You could get your list first and then loop through that list with a map and request the gender for each name. Remember that you have to wait for all promises to resolve inside your map before you can proceed.

const axios = require('axios');

async function getPeople() {
    let firstResult = await axios.get('api/path/endpoint1');
    // firstResult = [{name: "John", id: 1}, {name: "Anna", id: 2}]

    let updatedResult = firstResult.map(async item => {
        let people = await axios.get('api/path/endpoint2' + item.name); // or however your endpoint is designed 
        // people = {name: "John", id: 1, gender: male}
        item.gender = people.gender;
        return item; 
    });
    // updatedResult = undefined

    Promise.all(updatedResult)
        .then(finalResult => console.log(finalResult));
    //  [{name: "John", id: 1, gender: male}, {name: "Anna", id: 2, gender: female}]
}

Upvotes: 1

Related Questions