lightweight
lightweight

Reputation: 3327

handling a null get in res.json

I got a nodejs app built like this:

app.get('/customer/:ent_cust_id', function (req, res, next) {
    var query = 'Select * from entcustinfo where ent_cust_id = ' + req.params.ent_cust_id;
    console.log('Select * from entcustinfo where ent_cust_id =' + req.params.ent_cust_id);
    client.execute(query, function (err, result) {
    if (err) return next (err);
    var row = result.rows[0];
    //Response
    res.json({ent_cust_id: req.params.ent_cust_id, name: row.get('offers')});
});
});

but it causes node to shut down like this when the results of the array come back empty...

[root@ip-10-205-116-141 cassapi]# /usr/local/bin/node app.js
Example app listening at http://0.0.0.0:3030
Select * from entcustinfo where ent_cust_id =1106667844
events.js:87
      throw er; // Unhandled 'error' event
            ^
TypeError: Cannot read property 'get' of undefined
    at /home/ec2-user/cassapi/app.js:16:14
    at readCallback (/home/ec2-user/cassapi/node_modules/cassandra-driver/lib/request-handler.js:195:5)
    at Connection.invokeCallback (/home/ec2-user/cassapi/node_modules/cassandra-driver/lib/connection.js:567:5)
    at Connection.handleResult (/home/ec2-user/cassapi/node_modules/cassandra-driver/lib/connection.js:507:8)
    at ResultEmitter.emit (events.js:120:17)
    at ResultEmitter.each (/home/ec2-user/cassapi/node_modules/cassandra-driver/lib/streams.js:437:17)
    at ResultEmitter._write (/home/ec2-user/cassapi/node_modules/cassandra-driver/lib/streams.js:421:10)
    at doWrite (_stream_writable.js:303:12)
    at writeOrBuffer (_stream_writable.js:290:5)
    at ResultEmitter.Writable.write (_stream_writable.js:219:11)

I've tried to adjust app.get like this to check to see if the array is empty:

app.get('/customer/:ent_cust_id', function (req, res, next) {
        var query = 'Select * from entcustinfo where ent_cust_id = ' + req.params.ent_cust_id;
        console.log('Select * from entcustinfo where ent_cust_id =' + req.params.ent_cust_id);
        client.execute(query, function (err, result) {
        if (err) return next (err);
        var row = result.rows[0];
            if (row.get('ent_cust_id') = '') {
                res.send('ent_cust_id: ' + req.params.ent_cust_id + ' not found. Not all data is loaded.');
        } else {
            var row = result.rows[0];
                //Response
                res.json({ent_cust_id: req.params.ent_cust_id, accts: row.get('accts'), offers: row.get('offers')});
        }
        });
 });

I'm thinking I need an if statement to check if no records were returned in results.rows and then do an res.send. I tried that but the same behavior still occures. How do I find out if no records were returned?

EDIT:

Made code changes in the first part...pasted in the wrong code...clarified question too.

Upvotes: 1

Views: 3601

Answers (3)

Tom
Tom

Reputation: 979

It depends on the exact behavior of your client.execute(sql, callback(err, result)) function. You just have to test for what it returns on no results.

Ordinarily a callback from a database query will pass an empty array as the result if there are no results. So if you handle the case where result.length==0, you will no longer be trying to reference result[i].row.get on rows that no longer exist.

Although it is not the cause of this particular problem, you also want to escape your SQL queries. There is really no downside and it significantly increases your application security.

Upvotes: 1

Mike Horstmann
Mike Horstmann

Reputation: 588

//in your require, consider using below:
//var body-parser = require('body-parser'); // after installing with npm. I recommend globally installing
//app.use(body-parser()); //make sure you add this to initialize body parser after installing it.  *NOTE: If using node with express 4.~ this is deprecated so ignore.

app.get('/customer/:ent_cust_id', function (req, res, next) {
        //Your code: var query = 'Select * from entcustinfo where ent_cust_id = ?' [req.params.ent_cust_id];
  /* Above, should probably include a plus sign between "?'" and "[req.params.....]; as below:   */
        var query = 'Select * from entcustinfo where ent_cust_id = ?' + [req.params.ent_cust_id];
        //Another typo detailed below
  //Your code: consolelog('Select * from entcustinfo where ent_cust_id = ?');
  console.log('Select * from entcustinfo where ent_cust_id = ?');
  /* Also, at this point you want to be logging your full query var, not your manually entered string value so type this as below:   */
  console.log(query); // shows your query, not your manually typed string.
  //There really shouldn't ever be an issue with your manually typed query unless you need it surrounded in quotes.
  //For greater clarification, whatever you're calling client below should be defined and expanded upon with an example.  
  
  /* In this code snippet, I typically always send the response first, if there is NOT an err liks so: if(!err){ //do the client's stuff first, else (if there's an error, does not need to be defined) { //do whatever else }  Handling errors after it adds a small bit of speed to your process and reduces a step if you get a valid response and leaves error responding to secondary processing under the expectation you won't encounter an error  */
    client.execute(query, function (err, result) {
    if(!err) { //do your client stuff first if no error then return next.
    } else { console.log(err); return next} ; //No conditional needed for the error, because you've gotten here due to your code not working.
      
    //if (err) return next (err);
    var row = result.rows[0];
    //Response
    res.json({ent_cust_id: req.params.ent_cust_id, name: row.get('offers')});  /* Here you're responding with a JSON object as if you were querying a large JSON file.  You may want to consider using res.send with and application/json response type.  */
      
});
});
<div> For additional explanation on routing, you may want to look at express documentation here: <a href="http://expressjs.com/4x/api.html#res.json">express res.json</a></div>

<p> Also, make sure you're requiring body-parser in node so you can interpret incoming routes! </p>

<code> npm install -g body-parser </code>

Upvotes: 0

salezica
salezica

Reputation: 77029

Let's attack the problem. First, your error:

TypeError: Cannot read property 'get' of undefined

This is node telling you that you wrote <object>.get, but when it tried to access the get property, it found that <object> was undefined.

Even more so, it's telling you where it happened:

/home/ec2-user/cassapi/app.js:16:14

Go to that file, and take a look at line 16. It's probably one of the 2 you posted:

app.get('/customer/:ent_cust_id', ...)
// or
row.get('offers')

So, you think app or row are objects with a get() method, but one of them must be undefined. This can happen for 2 reasons:

  • The app has a value of undefined-- was it assigned? Is it coming from another function? Did that function forget to return?
  • The row variable, assigned to result.rows[0], is undefined. Does result.rows have a [0] element? Could the array be empty?

Check the part where you create the app object, and the results you obtain .row[0] from. Use console.log to see their values. The error should be easy to spot.

Upvotes: 0

Related Questions