0

Within a javascript class function, I'm unable to access outside variables (and therefore this) within a then scope.

I've referred to this article as well as it's duplicates Object method with ES6 / Bluebird promises

I'm aware that the following is a valid solution for accessing the desired this inside of a then scope:

var a = this;
one().then(function () {
  console.log(a)
});

However, I can't seem to get it working this way inside the context of a class. Here is the class:

var outerestThis = 'foo'

export class Listener {
  start() {
    this.listenForSearch();
  }
  listenForSearch() {
    var outererThis = 'foo';

    const search = () => {
      var outerThis = 'foo';
      let artistName = $('#search-input').val();
      new ArtistSearch(artistName).fetch_and_render().then(function () {
        debugger;
          this.starListener();
      });
    }
    $('#search-button').click(function () {
      search();
    });

  });
  }

  starListener() {
    ...
  }
}

When I hit the debugger inside of const search() inside the then scope, I expect that I should be able to access outer varables (which I would change to outer this when I get things working). But, outerThis, outererThis and outerestThis are all undefined.

Benjamin Lee
  • 1,014
  • 10
  • 24

1 Answers1

1

The problem isn't that you can't access outside variables. Javascript is lexically scoped, which means that variables in outer scopes are always available within inner scopes (as in your example).

The real problem you're having is that this is being redefined within your function because functions defined using the function keyword have dynamic context (meaning the this keyword changes its meaning depending on its environment). What you want to do is preserve the meaning of this from the class into the function. There's many ways to do this.

You could reference this using another variable, say self:

  const self = this; //self will not be changed within the function
  new ArtistSearch(artistName).fetch_and_render().then(function () {
    debugger;
      self.starListener();
  });

You can also explicitly set the context using the bind property, as others have mentioned:

  new ArtistSearch(artistName).fetch_and_render().then((function() {
    debugger;
      this.starListener();
  }).bind(this));

The most concise way, however, is to use an arrow function. Arrow functions have lexically inherited context, meaning this within an arrow function will always mean whatever this meant in the area the function was defined.

  new ArtistSearch(artistName).fetch_and_render().then(() => {
    debugger;
      this.starListener();
  });

Hope this has been helpful!

James M. Lay
  • 2,270
  • 25
  • 33