Reputation: 1933
I have defined a prototype class with few properties and methods and for some reason I cannot access all the properties in some cases (mainly when callbacks are involved).
Here is my code (removed some lines to make it clearer)
var Lobby = function (preloader, serverConn) {
// Hold a reference to EventBus
this.serverConn = serverConn;
this.preloader = preloader;
this.session_id = null;
this.scheduleItemService = new ScheduledItemService(this.preloader);
// Instantiate lobby stage
this.stage = new createjs.Stage("lobbyCanvas");
};
Lobby.prototype._renderLobbyImages = function(stage, scheduleItemService) {
// at this point, 'stage' and 'scheduleItemService' are valid!
..
// onScheduledItemClick callback function
this.scheduleItemService.render(stage, this._onScheduledItemClick);
}
Lobby.prototype._onScheduledItemClick = function(event) {
(function(inst) {
inst.serverConn.asyncSend(
'game.lobby',
{ 'action' : 'claim_scheduled_item',
'session_id' : inst.session_id, **//Here, 'inst.session_id' is DEFINED!**
},
function (error, reply) {
**// Here, both 'stage' and 'scheduleItemService' are UNDEFINED! WHY?!?!**
inst.scheduleItemService.startCountdown(inst.stage);
}
});
})(this);
}
ScheduledItemService.prototype.render = function(stage, onScheduledItemClick) {
var scheduled_item = new createjs.Bitmap(preloader.getResult("scheduled_item_img"));
..
..
scheduled_item.addEventListener('click', onScheduledItemClick);
..
}
Why this.session_id is defined in 'this' while 'stage' and 'scheduleItemService' are not defined?? these 3 are properties of Lobby class...
I tried browsing in 'this' pointer and I really couldn't find 'stage' nor 'scheduleItemService'.
I'm missing something, right?
Thank you :-)
Upvotes: 1
Views: 40
Reputation: 3065
Your scheduleItemService
variable is out of scope here
function (error, reply) {
scheduleItemService.startCountdown(stage);
}
The thing is even if you did not use Promises, this code would still fail. If you want to define the renderLobbyImages
and onScheduledItemClick
as prototype methods, you'd have to write
Lobby.prototype.renderLobbyImages = function(){
// this refers to a Lobby instance
this.scheduleItemService.render(stage, this.onScheduledItemClick);
}
Lobby.prototype.onScheduledItemClick = function(){
// this refers to a lobby instance
}
You must also use the use this
keyword in the onScheduledItemClick
.
Then, inside the promise callback you defined, the "this
" keyword does not point back to the instance. That's why you are getting errors with your code. Inside this callback, the this
changes.
To fix this, before the callback, store a temporary variable to the "this
, here I named it scope
". You can use this scope
the same way you use this
.
Lobby.prototype.onScheduledItemClick = function(event) {
// this refers to a lobby instance
var scope = this;
this.serverConn.asyncSend(
'game.lobby',
{
'action' : 'claim_scheduled_item',
'session_id' : scope.session_id.bind(scope), // Here scope instead of this. But you could use this as not inside callback. I used scope just for consistency
},
function (error, reply) {
// this does NOT refer to a lobby instance. You must use scope
scope.scheduleItemService.startCountdown(stage);
}
});
Edit 1
After your code edit, I can still see some errors.
I see that in your Lobby.prototype._onScheduledItemClick
, you are using a (inst)
variable, this.serverConn.asyncSend
, it should be inst.serverConn.asyncSen
--
Edit 2
Another problem with your code is the callback. The scope is not passed along. You have to "bind" your callback with a scope. This is used using function.bind();
So now, your line looks like :
this.scheduleItemService.render(stage, this._onScheduledItemClick.bind(this));
This will make it so that when your callback is called, the "this
" variable will have the value of the argument you pass in bind
.
Upvotes: 1
Reputation: 2977
Firstly, you aren't prefixing your things with this
. Unlike some other languages, this
is not optional in JavaScript.
When you enter a new function call, this
is redefined. You'll want to save a reference to it.
this
is defined as the parent of the called function. Therefore it changes each time a function is called. Here's what people often do:
Something.prototype.foo = function() {
var self = this;
doSomething(function() {
// now this has changed, but self still references the original this
});
};
Upvotes: 0