0

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!

Edoardo
  • 657
  • 7
  • 24
lucky simon
  • 241
  • 1
  • 6
  • 22
  • If you `console.log(result)` what does it show you? If `result` is an empty array (empty set) then item at index 0 is undefined. Therefore it does not have the property activated. – Jtaks Feb 08 '19 at 16:53
  • i get [] with the console.log(result) – lucky simon Feb 08 '19 at 17:07

2 Answers2

2

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.

Nipun Chawla
  • 356
  • 2
  • 8
  • Thank you that worked. (well still need to correct some code). could you please explain to me what this line do? I don't really understand – lucky simon Feb 08 '19 at 16:50
  • This is a conditional statement it will work like if there is an element is an array then it will return the length of that array otherwise it will return false. – Nipun Chawla Feb 08 '19 at 16:52
  • It is a [ternary operator](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Conditional_Operator) – Jtaks Feb 08 '19 at 16:55
1

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.

Jtaks
  • 281
  • 2
  • 5
  • 13
  • thank you for this detailed explination. So if I understand correctly, I check this answer when I do the DB request ? – lucky simon Feb 08 '19 at 17:46
  • I still don't understand something. When I put a "discord_key" that is in my DB, it goes in my if (!activated). But when I put a random key that is not in my DB, I get the same thing. in the first case, activated = 'false' but in the 2nd case activate = undefine. Why does it still prints me : "null" ? it sould print me used for a key that doesn't exist – lucky simon Feb 08 '19 at 17:59
  • @luckysimon That has to do with javascript and asynchronous callbacks. I'll update my answer with an explanation. – Jtaks Feb 08 '19 at 18:01
  • thank you. Yes I was looking at those earlier but it is hard to understand. – lucky simon Feb 08 '19 at 18:10
  • ok So i seperate my function into 2. I'll have a look. Thank you for your time! – lucky simon Feb 08 '19 at 18:25