0

so here is a situation that i have. I have a constructor function with many properties and methods. here are the properties:

var Brain = function(){
  this.util = require('util');
  this.fs = require('fs');
  this.assert = require('assert');
  this.Sequelize = require('sequelize');
  this.JsonField = require('sequelize-json');
  this.bcrypt = require('bcrypt-nodejs');
  this.bodyParser = require('body-parser');
  this.fileUpload = require('express-fileupload');

  // Custom Modules
  this.ModelsModule = require('./models');
  this.TombModule = require('./tomb');

}

a few of the methods are defined to call a given callback and pass data to it, for example:

Brain.prototype.db_read = function(request, response, data, callback) {
  var self = this;

  self.ModelsModule[data.Model].findOne(data.where)
  .then(function(obj) {
    // console.log(obj);
    callback(request, response, obj);
  })
  .catch(function(error){
    console.log(error);

  });

}

Here is the thing - the callback function is always going to be another method of the same constructor function. here is another method that would be a callback:

Brain.prototype.login = function(request, response, user) {
  var self = this;

  // console.log('form-data --- ', request.body);

  if(user == null || user == undefined) {
    console.log('Account Load: Failed');
    return response.render( self.TombModule.pages['login'], {error: 'Invalid Credentials'} );
  }
  else {
    // console.log(user.dataValues);
    if( self.bcrypt.compareSync(request.body.pswrd, user.dataValues.pswrd) == false ) {
      console.log('Account Load: Failed');
      return response.render( self.TombModule.pages['login'], {error: 'Invalid Credentials'} );
    }
    console.log('Account Load: Successful');
    request.session.you = {
      id: user.dataValues.id,
      f_name: user.dataValues.f_name,
      m_initial: user.dataValues.m_initial,
      l_name: user.dataValues.l_name,
      icon: user.dataValues.icon,
      background: user.dataValues.background,
      email: user.dataValues.email,
      phone: user.dataValues.phone,
      fax: user.dataValues.fax,
      uv: user.dataValues.uniqueValue
    };
    return response.redirect('/home');
  }

}

In my app.js a new instance of Brain is created.

const RoutinesModule = require('./routines');
const brain = new RoutinesModule.Brain();

The Entire chain of events starts from an express POST route:

app.post('/login', function(request, response){

  var data = {
    Model: 'Users',
    where: {where: {email: request.body.email}}
  }

  brain.db_read(request, response, data, brain.login);

});

Notice that the callback, the last parameter, for Brain.db_read is Brain.login, which is another method of the same constructor. here is where the problem is happening.

When POST requests to /login hits the app.js, it's going to query the database and give the results to any given function to handle it, in this case Brain.login

inside of Brain.db_read(), var self = this; works. it points to itself, the instance of the Brain. however, when it calls the callback which is Brain.login, the statement inside of Brain.login, var self = this; does not work. it results in undefined, causing an error.

Why is that happening? why is var self = this; inside of the Brain.login resulting in undefined?

Ultimately what i am trying to do is create a set of main functions to handle database operations(CRUD) instead of doing database operations inside of each individual function, which is/could be an indefinite amount.

I could easily just require that module in that function definition but i would strongly prefer to access its property for dynamic, scalable, and efficiency means.

Thanks!

ryanwaite28
  • 1,804
  • 2
  • 24
  • 40
  • The `self` variable you have created would be in scope in that callback function where you call `console.log(obj)` and `callback(request, response, obj)`. You could for example have used `callback.call(self, request, response, obj)`. But the `self` from that scope doesn't become magically available in the scope of that `login` method. – Bergi Feb 10 '17 at 05:02

1 Answers1

4

You're passing the method, brain.login, as a function that has no owner. You're just passing the function reference. You need to do brain.login.bind(brain).

Andy Ray
  • 30,372
  • 14
  • 101
  • 138
  • Wow, learn something new every day. Thanks! this solved everything!! so is that the general approach to defining the function owner when dealing with callback parameters? to just add a .bind() with the object we want to be the owner of the callback? – ryanwaite28 Feb 10 '17 at 04:36
  • Super quick response too! A+ – ryanwaite28 Feb 10 '17 at 04:36
  • `bind` works well in these scenarios. Not using `this` or `new` works even better. – Aluan Haddad Feb 10 '17 at 04:49