7

I am having trouble figuring out how to pass the objects method rather than sort "generic prototype" method when doing callback.

function Client() {
    this.name = "hello";
}

Client.prototype.apiCall = function(method, params, callback) {
    callback();
}


Client.prototype.onLogin = function(error, data) {
    console.log(this.name);// undefined!!!!
}

Client.prototype.start = function() {
    var self = this;
    self.apiCall('rtm.start', {
    }, self.onLogin) // passing of method like this does not work.
}

I am passing the onLogin method but well it does not work. This is code I have re-written. Previously I nested all methods inside the Client function but well, I learned that that is not the way to do it so now I am trying using prototype.

I know there is some solution "binding" the onLogin function inside the Client() function but well I want to understand the issue.

2 Answers 2

4

You need to bind the apiCalls context to the callback using bind:

Client.prototype.apiCall = function(method, params, callback) {
    var bound = callback.bind(this);
    bound();
}

Otherwise, the this within onLogin is set to the global object.

See Call, Apply And Bind for further details.

Basically .bind(obj) returns a function which, when called, will internally use (obj) as this.
So you create this bound and then you call it.

Sign up to request clarification or add additional context in comments.

Comments

3

You can use call or apply to bind this, see snippet. I've modified your code for demonstration purposes. Hope it clarifies things for you

function Client() {
  this.name = "hello";
}

Client.prototype = {
  apiCall: function(method, params, callback) {
    try {
      var trial = method.call(this, params);
      callback.apply(this, [null, trial]);
    } catch (e) {
      callback.apply(this, [e, null]);
    }
  },
  onLogin: function(error, data) {
    if (error) {
      Helpers.report('<b style="color: red">' +
        'An error occured!</b> <i>' +
        error.message + '</i>')
    } else {
      Helpers.report(this.name, ' (data.result = ' + data.result + ')');
    }
  },
  start: function() {
    Helpers.useCSS(1);
    
    // error from this.rtm.start
    Helpers.report('Command: <code>', 'this.apiCall(this.rtm.start, {will: \'not work\'}, this.onLogin);','</code>');
    this.apiCall(this.rtm.start, {will: 'not work'}, this.onLogin);
    // this.rtm.works is ok
    Helpers.report('<br>Command: <code>',
                   'this.apiCall(this.rtm.works, {will: \'work\'}, this.onLogin);',
                   '</code>');
    this.apiCall(this.rtm.works, {
      will: 'work'
    }, this.onLogin);
  },
  // --------------------------------
  // added rtm for snippet demo
  rtm: {
    start: function(params) {
      return anerror;
    },
    works: function(params) {
      return {
        result: 'worked, <code>params: ' + JSON.stringify(params) + '</code>'
      };
    }
  },
};

new Client().start(); //<= here
<script src="https://rawgit.com/KooiInc/Helpers/master/Helpers.js"></script>

3 Comments

this wil throw error because u are not appending properly on 49
I suppose that is browser dependent. Updated the snippet
sorry my mistake ..:) and +1 for the efort

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.