I am new to Node JS and I'm struggling to understand how to run a for loop inside an asynchronous function. There is another async function inside the for loop.
I should be getting a response of some values in promArray. However, I am getting an empty array.
const rp = require('request-promise');
const options2 = {
uri: 'uri',
method: 'GET',
auth: {
'user': 'username',
'pass': 'password'
}
};
var promArray = [];
function executeMethod() {
rp(options2).then(function(body) {
const jsonData = JSON.parse(body).result;
// iterate through the pods
jsonData.forEach(element => {
promArray.push(getProjectName(element.u_hig_proj_name.value))
});
});
return Promise.all(promArray);
}
function getProjectName(projectSysId) {
const projectTableAttrbutes = {
uri: 'uri',
method: 'GET',
auth: {
'user': 'username',
'pass': 'password'
}
};
return new Promise(function(res, rej) {
// call the project table
rp(projectTableAttrbutes).then(function(body) {
//console.log(JSON.parse(body).result.name);
res(JSON.parse(body).result.name);
})
})
}
// final execution
executeMethod().then(function(done) {
console.log(done);
});
2 Answers 2
The problem here is that your forEach is within the then block. That means that it will be executed asynchronously.
Your return statement however is located outside of the then, so it will be executed immediately, before the promise has resolved and the then block has run. Thats why it's empty.
This would be a possible solution:
function executeMethod() {
return rp(options2).then(function(body) {
const jsonData = JSON.parse(body).result;
// iterate through the pods
jsonData.forEach(element => {
promArray.push(getProjectName(element.u_hig_proj_name.value))
});
return Promise.all(promArray);
});
}
In this solution, the two promises are chained and executed consecutively. First, the outer promise is returned (return rp(...)). Within it's then block, the second promise is returned (return Promise.all(...)). That will be the final value, that executeMethod will resolve with.
I highly recommend checking out this article to learn more about promise chaining, since it is a crucial tool when working with promises.
Comments
When you first call executeMethod(), your promArray is empty, so all of the promises in the array (that is, all zero of them) are resolved, so the promise resolves right away. I'm guessing the promises you're actually interested in are those generated in the jsonData.forEach call, since you're adding those to promArray. Therefore, I'd recommend actually saying jsonData.map and then returning each of those getProjectName calls as promises, then wrap the whole .map call in Promise.all:
return Promise.all(
jsonData.map(
element => getProjectName(element.u_hig_proj_name.value)
)
);
And then you can use that like another promise.
Also, I don't quite understand what you're doing in the getProjectName function - why are you creating a new Promise wrapper around the request? It's already a promise.