As you can see from the code below what I'm trying to do is, create an array of objects with the following format:
[{Region: Africa, Countries: X, X, X}, {Region: Asia, Countries X, X, X}]
The X's are in place of country names. I am able to create this array of objects successfully.
When I'm done creating this array of objects, I want to do a res.send 200
to send the data. The issue is, in all previous configurations, I'd get an error because the res.send
would try to execute multiple times. Now I am attempting to do it with promises, and using Promise.all
. I am pretty sure I have incorrectly implemented it because now instead of producing anything, this code produces no output.
This code is so close to where it needs to be... if someone could show me what I'm missing here, that would be great. It has to be something with the promises.
router.get("/FRPListing", async (req, res) => {
//Array of all regions
//Have a country list
//Holder Array
let regCountryList = new Array()
//New Array
let countryList = new Array()
countryList.push("Europe and UK", "Africa", "Middle East and Gulf", "Eurasia", "Asia", "Australasia", "North America", "Central America Caribbean", "South America", "Global")
countryList.forEach(async function (value) {
let EuropeUK = await FRPObj.find({Region: value}, 'Region Country').sort({Country: 1}).distinct('Country').exec()
let EuropeUKRegCountryList = new Object()
EuropeUKRegCountryList.Region = value
EuropeUKRegCountryList.Countries = EuropeUK
regCountryList.push(EuropeUKRegCountryList)
})
Promise.all(regCountryList).then(values => {
res.send({status: 200, results: regCountryList})
});
});
CodePudding user response:
There's seems to be missing information in your question. It would be better if you could post a minimal reproducible example.
I think you are not quite understanding what Promise.all
is for, and you're using it to wrap a data array, which doesn't do anything.
Instead, you should construct an array of promises (the calls to your data services,) and pass that to Promise.all
. Promise.all
will invoke all of the promises passed to it, and wait for them all to resolve.
While you're working on the code, it might be good to rename some of the variables to be a little clearer about the intention.
Something like this should be close. Some of the details might not be right, depending on what your service calls actually return, for example. Also, you may want to handle error cases!
// You shouldn't need the `async` keyword decorating this function
// if you're handling the callback using promises. If you were using
// "await" within the callback, for example, you would need it.
router.get("/FRPListing", (req, res) => {
const regions = ["Europe and UK", "Africa", "Middle East and Gulf", "Eurasia", "Asia", "Australasia", "North America", "Central America Caribbean", "South America", "Global"];
const fetchCountries = [];
// First, build an array of promises (your async calls to your data source)
for (const region of regions) {
fetchCountries.push(
FRPObj.find({
Region: region
}, 'Region Country').sort({
Country: 1
}).distinct('Country').exec();
);
}
// Promise.all will return a results array with one entry per
// promise, and they will be in the order in which the original
// promises were pushed into the array. Because the order is
// preserved, you can look up the region from the regions.
Promise.all(fetchCountries).then(results => {
const aggregatedResults = [];
for (let i = 0; i < regions.length; i ) {
const region = regions[i];
const countries = results[i];
aggregatedResults.push({
Region: region,
Countries: countries
});
}
res.send({
status: 200,
results: aggregatedResults
});
});
});