How to wait for for loop with async requests to finish in node.js?
For your use case, using await
with Promise.all
is probably the most performant way to go about it. Your code should look something like this:
res.setHeader('Content-Type', 'application/json');
const sub = req.query.days_subtract;
const enddate = req.query.end_date;
var promiseArray = [];
for (var i = 0; i < sub; i++) {
promiseArray.push(new Promise((resolve, reject) => {
request("https://api.nasa.gov/planetary/apod?date=" + subtractDate(enddate, i) + "&api_key=DEMO_KEY", function(error, response, body) {
if (error) reject(error);
else resolve(body)
})
}))
}
res.send(await Promise.all(promiseArray));
Use something like request-promise. If you await each request in the for loop, then all requests are done in series. If each request is independent and doesn't need to be done one after the other, this is inefficient. The best way to handle something like this is to do them all in parallel and then wait for them all to complete. This is done by creating an array of request promises and then using await Promise.all(promiseArray)
to wait for all promises to resolve.
var promises = [];
for (var i = 0; i < sub; i++) {
const promise = request("https://api.nasa.gov/planetary/apod?date=" + subtractDate(enddate, i) + "&api_key=DEMO_KEY");
promises.push(promise);
}
const array = await Promise.all(promises);
To use async/await, you need to use a HTTP library that returns promises instead of using callbacks.
It's well worth using a library that can do this. A good option for a different library is node-fetch
, which effectively implements the "Fetch API" as implemented by browsers.
You can then simply await fetch(url)
.
async/await works so well and is becoming so common-place, I can highly recommend switching to frameworks and libraries that treat it as a first-class citizen instead of an afterthought. This includes Express, which is also a callback-based library, instead of a Promise-based one. But that's slightly off-topic.