1

I tried my best to replicate the error outside my context but failed so, so I'll have to provide with it.

Code :

var view;

widget = {
    activated: false,
    close: function(){
        this.view.popupManager.enabled = false;
    }
}

view = new MapView({
}).then(function(){ //then is triggered when fully loaded;
    console.log(this.popupManager) //Object!
    widget.activated = true;
    widget.view = this;
}

console.log(view.popupManager) //Undefined, not loaded yet

$('#my_button').click(function(){
    if(widget.activated){
        widget.close() //this.view.popupManager is undefined
    }
})

This is using Esri's Javascript 4.3 API, but it doesn't seem to be the API, but some misuderstanding of my part on how scope works in Javascript.

As you can see, even though I only call widget.close if view is fully loaded, it still referencing the old, not fully loaded object

What am I missing?

Mojimi
  • 2,561
  • 9
  • 52
  • 116
  • You describe exactly what is happening: It's not loaded *yet*. – Bergi May 10 '17 at 19:19
  • Does it work any better if you replace `widget.view = this`; with `widget.view = view;`? – CaptEmulation May 10 '17 at 19:19
  • @Bergi if "then" is called it means it is loaded – Mojimi May 10 '17 at 19:25
  • @Mojimi The callback in `.then()` is called asynchronously, so it doesn't happen until after you do `console.log(view.popupManager);` – Barmar May 10 '17 at 19:26
  • 1
    This has nothing to do with async functions. If you read the code you'll see that the described error can __only__ occur after everything's loaded. It's a `this` issue. – clinton3141 May 10 '17 at 19:31
  • @Mojimi Yes, but your `console.log(view.popupManager)` is not inside the `then` callback. If you'd put it there, it would work (sans the `this` confusion) – Bergi May 10 '17 at 19:33

1 Answers1

4

The problem here is that this isn't always what you think it is. There are a couple of thiss in your code, and each is different.

Welcome to JavaScript's often misunderstood this.

In the code

widget = {
    activated: false,
    close: function(){
        this.view.popupManager.enabled = false;
    }
}

this will refer to the widget.

Now in the code inside the then callback, this will refer to the window object, so you're essentially saying widget.view = window. This this is probably the one which is catching you out.

I suspect that what you mean is to set the widget's view to the new view, in which case you will need to update the code as follows:

var view;

widget = {
    activated: false,
    close: function (){
        this.view.popupManager.enabled = false;
    }
}

view = new MapView({
}).then(function () {
    widget.activated = true;
    widget.view = view; // set the widget's view correctly
});

$('#my_button').click(function(){
    if(widget.activated){
        widget.close();
    }
});
clinton3141
  • 4,751
  • 3
  • 33
  • 46