Skip to content Skip to sidebar Skip to footer

Javascript Oop - Lost This In Asynchronous Callback

I have problem which still bothers me on js oop - I'm sure I'm doing it bad, but I cant get how to do it right. For example, I have this code Auth.prototype.auth = function () {

Solution 1:

There are a couple of ways to do this. The most direct is to simply save a copy of the value you need:

Auth.prototype.auth = function () {
    var request = newXMLHttpRequest();
    var self = this; // save "this" value

    request.open('GET', this.getAuthServerURL() + '/token', true);
    request.send();

    request.onloadend = function () {
      var response = JSON.parse(request.responseText);

      console.log(response);
      if(response.result == 'found') {
        var token = response.token;

        self.setToken(token); // use saved "this" value
        self.isSigned = true;
      } else {
        console.log('Not logged yet.');
      }
    }
}

Another way is to use bind:

request.onloadend = (function () {
  var response = JSON.parse(request.responseText);

  console.log(response);
  if(response.result == 'found') {
    var token = response.token;

    this.setToken(token); // use saved "this" valuethis.isSigned = true;
  } else {
    console.log('Not logged yet.');
  }
}).bind(this);

The second approach is "cleaner", but it has browser compatibility issues (IE < 9 does not support it).

Solution 2:

.bind the function:

Auth.prototype.auth = function () {
    var request = newXMLHttpRequest();

    request.open('GET', this.getAuthServerURL() + '/token', true);
    request.send();

    request.onloadend = function () {
      var response = JSON.parse(request.responseText);

      console.log(response);
      if(response.result == 'found') {
        var token = response.token;

        this.setToken(token);
        this.isSigned = true;
      } else {
        console.log('Not logged yet.');
      }
    }.bind(this); //<-- bound
}

Solution 3:

You can just capture a reference to it in the outer scope, I've used the identifier self, however please feel free to give the name a more semantic meaning:

varself = this;
request.onloadend = function () {
  ...
  self.setToken(token);
  ...
};

Solution 4:

Capture this before the callback:

Auth.prototype.auth = function () {
    var self = this;

    var request = newXMLHttpRequest();

    request.open('GET', this.getAuthServerURL() + '/token', true);
    request.send();

    request.onloadend = function () {
      var response = JSON.parse(request.responseText);

      console.log(response);
      if(response.result == 'found') {
        var token = response.token;

        self.setToken(token);
        self.isSigned = true;
      } else {
        console.log('Not logged yet.');
      }
    }
}

Solution 5:

Save this in a local var outside the callback.

Auth.prototype.auth = function () {
    var request = newXMLHttpRequest();
    var _this = this;

    request.open('GET', this.getAuthServerURL() + '/token', true);
    request.send();

    request.onloadend = function () {
      var response = JSON.parse(request.responseText);

      console.log(response);
      if(response.result == 'found') {
        var token = response.token;

        _this.setToken(token);
        _this.isSigned = true;
      } else {
        console.log('Not logged yet.');
      }
    }
}

Post a Comment for "Javascript Oop - Lost This In Asynchronous Callback"