szier
szier

Reputation: 1507

Cannot push into an array from Mongoose then statement

Background: A Market collection has a url property that stores an array of urls from selected sites from the Site collection. I created a helper (code below) that I could call from /routes/markets.js that essentially selects the Market based on req.params.url and then loops over the market.sites array and finds the corresponding Site, storing them into an array that I can use when the view is rendered.

Issue: Calling the push function on the array doesn't actually push anything and in the last console.log statement I have simply logs []

Question: How can I push into this array? Is this an issue with the for of loop and then Promise call?

market-helpers.js

exports.listSites = (req, res, errorRender, successRender) => {
  let sites = [];
  Market.find({url: req.params.url})
    .then((market) => {
      for (url of market[0].sites)
        Site.find({url}).then((site) => {
          sites.push(site[0]);
        }).catch((err) => console.log(err));

      console.log(sites);
      res.render(successRender, {sites});
    })
    .catch((errors) => {
      res.render(errorRender, {errors});
    });
};

routes/markets.js

router.get('/:url', (req, res) => {
  Markets.listSites(req, res, 'login-markets', 'markets/index');
});

Upvotes: 2

Views: 147

Answers (1)

cubbuk
cubbuk

Reputation: 7920

Site.find({url}) is an async operaration therefore res.send is executed before waiting for the result of async operation. You can wait for result of all async operations using Promise.all and once all of them are resolved you can return the response as follow:

exports.listSites = (req, res, errorRender, successRender) => {
  let sites = [];
  Market.find({url: req.params.url})
    .then((market) => {
      const promises = [];
      for (url of market[0].sites)
            promises.push(Site.find({url}).then((site) => sites.push(site[0])));

      return Promise.all(promises).then(() => {
          console.log(sites);
          res.render(successRender, {sites});
      });
    })
    .catch((errors) => {
      res.render(errorRender, {errors});
    });
};

Upvotes: 1

Related Questions