Search code examples
node.jsfunctionapifor-looppug

NODEJS, PUG, EXPRESS - Cannot read property 'length' of undefined


I have an API that i tweaked to make 2 calls to my DB and pull down information .. I can see the results in my console log so i know it is working

The next part is when it renders the view i need to show the results in two places

Here is the code for the API that makes 2 calls to the DB

function apples(req, res, next) {
  sql.connect(config, function () {
    var request = new sql.Request();
    request.query("select price from table WHERE fruit = 'apples'", function(err, recordsetapples) {
      var arrayLength = recordsetapples.length;
      for (var i = 0; i < arrayLength; i++) {
        console.log(recordsetapples[i]["price"]);
      };
      res.render('index', { resultsapples: recordsetapples });
        return next();
    });
  });
};

function pear(req, res, next) {
  sql.connect(config, function () {
    var request = new sql.Request();
    request.query("select price from table WHERE fruit = 'pear'", function(err, recordsetpear) {
      var arrayLength = recordsetpear.length;
      for (var i = 0; i < arrayLength; i++) {
        console.log(recordsetpear[i]["price"]);
      };
      res.render('index', { resultspear: recordsetpear });
        next();
    });
  });
};



app.get('/fruit', apples, pear);

So after that runs I can see the price print in console log .. Then i see this error

Cannot read property 'length' of undefined

What i expect to see if the price appear ... To get that info i have this code

      tr
        th.hidden-phone Fruit
        th.hidden-phone Price
      tr
      each val in resultsapples
        td.hidden-phone Apples
        td.hidden-phone !{val.price}
      tr
      each val in resultspear
        td.hidden-phone Pears
        td.hidden-phone !{val.price}

Solution

  • The problem is your view expects both lists at the same time but you attempt to render the view twice with each list separately, which means in either scenario one list in the view will be undefined.

    Even if you were to fix this, this approach won't work anyway because after the first res.render the HTTP response will end and return to the client. Ideally you would want to make one trip to the DB for both resultsets and then render the view e.g.

    sql.connect(config, () => {
      const request = new sql.Request();
      request.query("select price from table WHERE fruit = 'apples' OR fruit = 'pear'", (err, result) => {
        res.render('index', { 
          resultsapples: result.recordsets[0], 
          resultspear: result.recordsets[1]
        });
      });
    });