0

I'm getting an error accessing the variables in this class when running a 'constructor' script. Any thoughts?

/**
 * Info
 */
exports.sqlWhiteList = function(){

    var sqlImport = require('../DBConnectors/MYSQLConn.js');
    var sql = new sqlImport.sqlConn();

    //fill up static variables
    this.tables = {};
    this.attributes = {};

    //populate the table names
    sql.performQuery(('xxxxxx xxxxx = \'BASE TABLE\' ' +
        'AND TABLE_SCHEMA=\'' + sql.credentials.database + '\''),function(rows){

        for (var index in rows){
            this.tables[rows[index]['TABLE_NAME']] = true; // this fails
        }
    });
};

Error = "TypeError: Cannot read property 'tables' of undefined"

Leonid Beschastny
  • 43,908
  • 9
  • 107
  • 112
William Falcon
  • 9,426
  • 11
  • 59
  • 106
  • This is creating an index to look up DB table names. It says "TypeError: Cannot read property 'tables' of undefined" – William Falcon Jul 19 '14 at 20:30
  • On a side note, you should really consider a `noSQL` database for node, e.g., [mongoose](http://mongoosejs.com). Makes everything so much better. – royhowie Jul 19 '14 at 20:32
  • Agreed, but we have to support a SQL DB right now, so I'm trying to create modules to connect to any kind of DB – William Falcon Jul 19 '14 at 20:32
  • 1
    I didn't downvote but I suspect whoever did was wondering what this error you mention actually looked like. – Pointy Jul 19 '14 at 20:33
  • 1
    As a side note, read this to get a proper understanding of how "this" works in js: http://stackoverflow.com/questions/13441307/how-does-the-this-keyword-in-javascript-act-within-an-object-literal/13441628#13441628 – slebetman Jul 20 '14 at 02:36

1 Answers1

1

You just need to stash this in the outer function so that the callback can get to the right value:

var moduleObj = this;

// ...

//populate the table names
sql.performQuery(('xxxxxx xxxxx = \'BASE TABLE\' ' +
    'AND TABLE_SCHEMA=\'' + sql.credentials.database + '\''),function(rows){

    for (var index in rows){
        moduleObj.tables[rows[index]['TABLE_NAME']] = true; // this fails
    }
});

Also I would very strongly suggest not using a for ... in loop to iterate over the rows returned from the query. I'm not familiar with the API but I'm willing to bet that it's a real JavaScript array. You should use either a plain for loop with an index variable, or else a .forEach() call. Using for ... in for arrays is sort-of a bad practice for a few reasons, not the least of which is that it causes V8 (and maybe other runtimes) to abandon any attempt at serious optimization of a function's code in some cases. One of those cases is when you're using it on an array, apparently.

Pointy
  • 371,531
  • 55
  • 528
  • 584
  • Still getting the error: "TypeError: Cannot read property 'tables' of undefined" It seems the class is undefined?? – William Falcon Jul 19 '14 at 20:33
  • You added that `var` declaration *inside* the "sqlWhiteList" function, right? Oh wait hold on; "module" might not be the best variable name to use :) However that shouldn't cause that particular problem, I don't think. – Pointy Jul 19 '14 at 20:34
  • yup. So it should be before the export line? – William Falcon Jul 19 '14 at 20:35
  • @WilliamFalcon no it should be inside the function. The error is happening in the SQL callback, right? Well that doesn't make a lot of sense, because if `this` in "sqlWhiteList" were `undefined` then those assignments to properties of `this` would have failed too. – Pointy Jul 19 '14 at 20:36
  • @WilliamFalcon the point of this is that when the SQL function executes your callback, the value of `this` will no be the same as it is *outside* that callback; it'll be whatever the SQL API decides it should be. By saving `this` in another variable in the "sqlWhiteList" function, you make it possible for that callback to access the object you need it to access. – Pointy Jul 19 '14 at 20:37
  • Ok. It turns out the module word may have been a reserved word, so I just changed the name of the var and it works. Thanks. Any links I can read to explain why this is necessary? Just starting JS from java/c and OOP seems to be a challenge. – William Falcon Jul 19 '14 at 20:38
  • @WilliamFalcon the best thing to do when going to JavaScript from any other C-like language is to remember to make no assumptions about how stuff works :) In particular, the way `this` works is *completely* different, really. There's no permanent relationship between a function and any particular object. The value of `this` is determined dynamically based on the nature of each function call. – Pointy Jul 19 '14 at 21:02
  • @WilliamFalcon [this MDN page is OK](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this) and there are some SO questions with excellent answers. They're hard to find unfortunately; [here is one](http://stackoverflow.com/questions/3127429/javascript-this-keyword). – Pointy Jul 19 '14 at 21:04
  • @Pointy, @WilliamFalcon, adding to your discussion, `self` is a conventional variable name for maintaining reference to `this`. – Leonid Beschastny Jul 19 '14 at 22:26