Allard Kragt
Allard Kragt

Reputation: 23

New API call for each value in an array

I basically want this kind of object as a result:

[{ id: 5040, requester_id: 1234, requester_name: 'John' }, { id: 5046, requester_id: 999, requester_name: 'Jim' }, { id: 5049, requester_id: 543, requester_name: 'Alex' }]

This is an object of tickets and tickets have multiple properties.

The API I'm using has a call that receives the ticket. No problems retrieving this. The information I get from this API call is this:

[{ id: 5040, requester_id: 1234 }, { id: 5046, requester_id: 999 }, { id: 5049 requester_id: 543 }]

Based on each requester_id I need to do another API call to retreive the name of the requester. For requester_id 1234, it gives me this:

{ requester_id: 1234, name: 'John' }

Each requester requires its own API call to get this information.

If Nodejs were an async programming language, I would do something like this:

var tickets = api({ method: 'get', path: '/tickets' });
for (var i=0; i<tickets.length; i++){
  var contact = api({ method: 'get', path: '/contact/'+tickets[i].requester_id);
  tickets[i].name = contact.name;
}

Obviously, this doesn't work.

I have tried using callbacks, promises, different tools to get the API data (my preference now is 'request'). I have literally spent 8 hours and I can't get it to work.

I need the for loop to wait until the first API call is finished. Then I need each iteration of the loop to wait for the previous one to finish.

My API function returns a Promise like this:

return new Promise(function(resolve, reject) {
  request.get(options, function(err, resp, body) {
    if (err) {
      reject(err);
    } else {
      resolve(JSON.parse(body));
    }
  });
});

Out of many different failed attempts, this is the last one:

var tickets = [];
var contacts = [];

var insertContactData = function(reqId){
    return api({ method: 'get', path: '/contacts/'+reqId });
}

var main = function(){
  var myTickets = api({ method: 'get', path: '/tickets');
  myTickets.then(function(result) {
               var ticketData = result.results;

               for (var i=0; i < result.results.length; i++){
                 var thisTicket = {};
                 thisTicket.id = ticketData[i].id;
                 tickets[i] = thisTicket;
               }
               var contacts = [];
               for (var i=0; i < result.results.length; i++){
                 var idExists = false;
                 for (var j=0; j < contacts.length; j++){
                   if (contacts[j].requesterId == tickets[i].requesterId){
                     idExists = true;
                   }
                 }
                 if (idExists == false){
                   var newCont = {};
                   newCont.requesterId = tickets[i].requesterId;
                   contacts.push(newCont);
                 }
               }
               contacts.shift();
               for (var i=0; i < contacts.length; i++){
                 var pos = i;
                 var reqId = contacts[i].requesterId;
                 var contact = insertContactData(reqId);
                 
                 console.log(contact);
               }
             }, errHandler).catch(function(error){
               console.log('ERROR '+error);
             });
}

Please help?

Upvotes: 2

Views: 5981

Answers (1)

James
James

Reputation: 82136

If you need to wait for an asynchronous request before continuing then you can use async / await

async function loadTicketInfo() { 
  const tickets = await api({ method: 'get', path: '/tickets' });
  for (let i=0; i<tickets.length; i++){
    var contact = await api({ method: 'get', path: '/contact/'+tickets[i].requester_id);
    tickets[i].name = contact.name;
  }
};

Although, depending on how many tickets you expect to pull, this could be a pretty slow operation. I suggest you pull all the ticket information in parallel, and then marry the information up at the end

const ticketInfos = tickets.map(t => api({ method: 'get', path: '/contact/' + t.requester_id));
const infos = await Promise.all(ticketInfos);
tickets.forEach(t => {
  const info = infos.find(i => i.requester_id === t.requester_id);
  if (info) {
    t.requester_name = t.name;
  }
});

Upvotes: 3

Related Questions