Viral Joshi Viral Joshi - 3 months ago 10
Node.js Question

Inner class functions usage in Node JS is throwing error

I am learning Node JS and I am learning how to create OOP structure in node. I have a simple class where I am using functions to check and create user in database. I am getting

TypeError
when I am calling class function inside a function. My codes of class,

var method = AccessRegisterAction.prototype;

function AccessRegisterAction(parameters) {

this._bcrypt = require('bcrypt-nodejs');
this._cassandra = require('cassandra-driver');
this._async = require('async');


this._uname = parameters.uname;
this._email = parameters.email;
this._passwd = parameters.passwd;

//Connect to the cluster
this._client = new this._cassandra.Client({contactPoints: ['127.0.0.1'], keyspace: 'testdb'});

//this._bcrypt.hashSync("bacon");

}

/*
* This method "createUser" is used to create new users
*
* First it will check for user's email is in database or not.
*
* If email is registered we will process accordingly,
* else we will process accordingly.
*
* */

method.createUser = function () {
var selectUserFromDBQuery = "SELECT uid from testdb.users WHERE email = '?' ALLOW FILTERING";

this._client.execute(selectUserFromDBQuery, this._email, function (err, result) {

//if there is not any error while fetching data
if (!err) {

//if there is result, it means we have email already registered
if (result.rows.length > 0) {

//so now we need to show user is already registered error
//to the user
this.errorWhileCreatingAccount(2);

} else {

//here we are checking user's username because
//we have not found user's email in database and we
//are good to go to register user
this.userNameCheck();


}
}
else {
this.errorWhileCreatingAccount(1);
}

});
};


/*
* This method will check for username in database.
*
* If there is username registered in database than we will
* show error that username is taken otherwise
* we will process to register user.
* */
method.userNameCheck = function () {
var checkUserNameQuery = "SELECT uid from testdb.users WHERE uname = '?' ALLOW FILTERING";

this._client.execute(checkUserNameQuery, this._uname, function (err, result) {

//if there is not any error while fetching data
if (!err) {

//if there is result, it means we have email already registered
if (result.rows.length > 0) {

//so username is taken and we need to tell user to
//use different username
this.errorWhileCreatingAccount(3);

} else {

//here we are registering user and adding information into database
this.newUserCreate();

}
}
else {
this.errorWhileCreatingAccount(1);
}

});

};

/*
* This method will create new user into database
*
* Simple as that
* */
method.newUserCreate = function () {
};


/*
* This function will throw an error which was occurred during the account creation process
* */
method.errorWhileCreatingAccount = function (errorCode) {
var _error = {error: "", msg: ""};

switch (errorCode) {
case 1:
_error.error = true;
_error.msg = "There was error while checking your information. Please try again.";
break;
case 2:
_error.error = true;
_error.msg = "You have already created account with this email. " +
"Please use forgot password link if you don't remember your login details.";
break;
case 3:
_error.error = true;
_error.msg = "Username that you chose is already taken. Please try different username.";
break;
default:
_error.error = true;
_error.msg = "There was error an error. Please try again.";
break
}

};


// export the class
module.exports = AccessRegisterAction;


And the error message I am getting is,

events.js:160
throw er; // Unhandled 'error' event
^

TypeError: this.userNameCheck is not a function
at /Users/user/Desktop/Projects/nodejs/testproject/application/classes/UserAccessAction/AccessRegisterAction.js:55:22
at next (/Users/user/node_modules/cassandra-driver/lib/utils.js:616:14)
at readCallback (/Users/user/node_modules/cassandra-driver/lib/request-handler.js:202:5)
at Connection.invokeCallback (/Users/user/node_modules/cassandra-driver/lib/connection.js:584:5)
at Connection.handleResult (/Users/user/node_modules/cassandra-driver/lib/connection.js:522:8)
at emitThree (events.js:116:13)
at ResultEmitter.emit (events.js:194:7)
at ResultEmitter.each (/Users/user/node_modules/cassandra-driver/lib/streams.js:482:17)
at ResultEmitter._write (/Users/user/node_modules/cassandra-driver/lib/streams.js:466:10)
at doWrite (_stream_writable.js:307:12)


and my codes where I calling this function is,

var param = {uname: "testname", email: "fake@test.com", passwd: "test123"};
var AccessRegisterAction = require('../application/classes/UserAccessAction/AccessRegisterAction');
var register = new AccessRegisterAction(param);
register.createUser();


so can anyone tell me where my mistake is? How can I use oop with nodejs?

Thanks

Answer

Since it looks like you're using ES5 style, I'm not going to recommend arrow functions. However, as was brought out in the comments, the value of this changes inside each function statement. So, you need to save the context you'd like to use before entering the inner functions. For example:

method.createUser = function () {
    var context = this;
    var selectUserFromDBQuery = "SELECT uid from testdb.users WHERE email = '?' ALLOW FILTERING";

    this._client.execute(selectUserFromDBQuery, this._email, function (err, result) {

    //if there is not any error while fetching data
    if (!err) {

        //if there is result, it means we have email already registered
        if (result.rows.length > 0) {

            //so now we need to show user is already registered error
            //to the user
            context.errorWhileCreatingAccount(2);

        } else {

            //here we are checking user's username because
            //we have not found user's email in database and we
            //are good to go to register user
            context.userNameCheck();


        }
    }
    else {
            context.errorWhileCreatingAccount(1);
        }

    });
};

Do this in each method which attempts to call this from within a new function.

Comments