Home > database >  Fetching an list of items from Mongoose and returning the results
Fetching an list of items from Mongoose and returning the results

Time:09-22

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
    });
  });
});

  • Related