Reputation: 23
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
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