lucky simon
lucky simon

Reputation: 291

cannot read the property of undefined

I am coding a server-side app in node JS and I am using a database in MySQL.

I get "TypeError: Cannot read property 'activated' of undefined"

The request I do should say "empty set" when I do it manually in the MySQL terminal.

When I try to use it in my code an I input and invalid discord_key, it returns an error, but I want it to return just a false alarm so I can catch it and use that info.

function checkKey(key) {
    var activated = "";
    var sqlcheck = "SELECT activated from authentification where discord_ key = ?";
    console.log("in function");
    DB.query(sqlcheck, [key], function (err, result) {
        if (err) throw (err);
        activated = result[0].activated;
    });
    if (!activated) {
        console.log("null");
        return ("NULL");
    } else {
        console.log("used");
        return ("used");
    }
}

I should get :

that request sends an empty set, so the key doesn't exist.

thank you for your help!

Upvotes: 1

Views: 5831

Answers (2)

Jtaks
Jtaks

Reputation: 301

The Error

The error is telling you that a variable you are using is undefined. It tells you this because you attempt to read a property from an undefined variable.

You mentioned result is an empty array. This means that any index you attempt to access returns undefined. For example:

let result = []
console.log(result[0] === undefined) // prints true

And in javascript, if you try and access a property of undefined, you get your error. Continuing our example:

result[0].activated // Throws error: Cannot read property 'activated' of undefined.

Since there is no guarentee that result[0] has a value, you should make sure it is not undefined before accessing it's properties. As @NipunChawla shows, one way is to check the array has a length (i.e at lease one value):

if (result.length) { // Does result have values?
  activated = result[0].activated
} else {
  activated = false
}

Better yet, if you know you are working with result[0] only, check whether it is defined directly:

if (result[0]) { // Does result[0] have a value?
  activated = result[0].activated
} else {
  activated = false
}

You are still left with the possibility that result[0].activated does not exist. Meaning activated would be undefined.

if (result[0] && result[0].activated) { // ... and does the first value
                                        // contain the property activated?
  activated = result[0].activated
} else {
  activated = false
}

So all together now:

DB.query(sqlcheck, [key], function (err, result) {
  if (err) throw (err);
  if (result[0] && result[0].activated) {
    activated = result[0].activated
  } else {
    activated = false
  }
})

Async Callbacks

To fix !activated in the second if statement always being true, you should look into how callbacks work. Basically DB.query goes off and does its thing. When it is done, it will execute the function you provided it as a callback. The order of execution looks something like this:

  1. Call DB.query to send a request to your database
  2. Continue execution of your script. i.e check if (!activated) { ...
  3. DB.query has now finished and calls your callback, assigning activated = result[0].activated. i.e function(err, result)

A quick way you could fix this would be like so:

function checkKey(key) {
  var activated = "";
  var sqlcheck = "SELECT activated from authentification where discord_ key = ?";
  console.log("in function");
  DB.query(sqlcheck, [key], function (err, result) {
    if (err) throw (err);
    if (result[0] && result[0].activated) {
      activated = result[0].activated
    } else {
      activated = false
    }

    doSomethingWithResult(activated)
  });
}

function doStuffWithResult(activated) {
  if (!activated) {
    console.log("null");
    // Do your !activated stuff
  } else {
    console.log("used");
    // Do your activated stuff
  }
}

See this question for more info.

Upvotes: 1

Nipun Chawla
Nipun Chawla

Reputation: 366

In case no result you can write this:

if (err) throw (err);
activated = result.length ? result[0].activated : false;

That will return false in case of no result.

Upvotes: 2

Related Questions