0

I am working with node.js and express. The problem arises while working with the routes. I have created an array named productList which I want to populate with json objects but my code is not working. The first console.log statement successfully logs the array of json objects but the second console.log statement logs the empty array.

router.get('/', (req, res) => {
  var productList = [] ;
  Products.find()
  .then(products => {
    products.forEach(product => {
    productList.push(product) ;
    console.log(productList) ; // First console.log
   })
  })
  .catch(err => res.status(400).json({'error': "Something wrong happened !!"}));

  console.log(productList) ;  // Second console.log
  res.render("products", {productList}) ;
});

Here Products is the name of a Document that is created successfully. I think the problem is related with the scoping of productList array. I don't understand what's wrong going on here. Please help.

Mohd. Shoaib
  • 113
  • 1
  • 6

1 Answers1

1

You're trying to use productList BEFORE is has been populated. Asynchronous operations in Javascript like Products.find() are asynchronous and non-blocking. That means they get started and then your code continues to run and some time LATER, the .then() handler is called.

So, the sequence of operations in your code is:

  1. Declare var productList = [].
  2. Call Products.find() which just starts the operation
  3. Execute second console.log(productList) ; which show the list as empty
  4. Call res.render("products", {productList}) ;
  5. Then, sometime later, the .then() handler for Products.find() gets called.

As you can see from that sequencing, you're trying to use productList with res.render() before it has any data in it.

The usual solution here is to put the res.render() INSIDE the .then() handler as that's the ONLY place in your code where you know the timing of when productList has been filled in properly like this:

router.get('/', (req, res) => {
  Products.find().then(productList => {
      console.log(productList);
      res.render("products", {productList}) ;
  }).catch(err => res.status(400).json({'error': "Something wrong happened !!"}));
});

Note, it does not appear that you need to copy over products to a new productList variable any more so I removed that extra step.

FYI, your .catch() handler should probably send a 5xx status which is typically what one would use when there was a database error.

jfriend00
  • 683,504
  • 96
  • 985
  • 979