Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using callback function with prototype functions

Tags:

javascript

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.

like image 239
Todilo Avatar asked Dec 20 '14 08:12

Todilo


People also ask

How do you call a function from a prototype?

The call() allows for a function/method belonging to one object to be assigned and called for a different object. call() provides a new value of this to the function/method. With call() , you can write a method once and then inherit it in another object, without having to rewrite the method for the new object.

Can a callback function call another function?

Yes. The print( ) function takes another function as a parameter and calls it inside. This is valid in JavaScript and we call it a “callback”. So a function that is passed to another function as a parameter is a callback function.

Can callback be asynchronous?

The callback is a function that's accepted as an argument and executed by another function (the higher-order function). There are 2 kinds of callback functions: synchronous and asynchronous. The synchronous callbacks are executed at the same time as the higher-order function that uses the callback.

What is a callback function and when would we use it?

A callback function is a function passed into another function as an argument, which is then invoked inside the outer function to complete some kind of routine or action.


2 Answers

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.

like image 186
helpermethod Avatar answered Sep 28 '22 23:09

helpermethod


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>
like image 34
KooiInc Avatar answered Sep 28 '22 21:09

KooiInc