I am having some trouble getting a callback function to work. Here is my code:
SomeObject.prototype.refreshData = function()
{
var read_obj = new SomeAjaxCall("read_some_data", { }, this.readSuccess, this.readFail);
}
SomeObject.prototype.readSuccess = function(response)
{
this.data = response;
this.someList = [];
for (var i = 0; i < this.data.length; i++)
{
var systemData = this.data[i];
var system = new SomeSystem(systemData);
this.someList.push(system);
}
this.refreshList();
}
Basically SomeAjaxCall is making an ajax request for data. If it works we use the callback 'this.readSuccess' and if it fails 'this.readFail'.
I have figured out that 'this' in the SomeObject.readSuccess is the global this (aka the window object) because my callbacks are being called as functions and not member methods. My understanding is that I need to use closures to keep the 'this' around, however, I have not been able to get this to work.
If someone is able show me what I should be doing I would appreciate it greatly. I am still wrapping my head around how closures work and specifically how they would work in this situation.
Thanks!
The following site seems to suggest that the problem may be more in your "class" building than in the usage. If you read down to the "rewrite using prototype properties", they write that that particular method of "class" structuring will keep the methods global instead of instance-based. Perhaps another creation method?
http://devedge-temp.mozilla.org/viewsource/2001/oop-javascript/
Your problem here is not exactly a closure or scoping problem. The problem is that when you assign
this.readSuccess
to a variable, you assign the function itself without any notion of the object it originaly belongs to.In the same way, you can take a regular, "stand-alone" function and use it as method of an object:
And your problem can be replicated in this example
So your problem is to assign this.readSuccess to some variable and having it called as a method of this. Which can be done with a closure as demonstrated by Pointy. Since I don't know what "SomeAjaxCall" actually does, it's hard to know if the value of
this
is actually lost and ifvar obj = this
is actually needed. Chances are that it's not, so you can be fine with this kind of code:In your case, that would be (edit: adding the arguments passed to the handler) :
As noted previously, several js frameworks offer a
bind
function to simplify this kind of issue. But you don't need a complete framework just for this : here is a perfectly fineFunction#bind
method that works an plain javascript:With the help of
Function#bind
, you can write:Well the most straightforward thing to do is to just wrap "this.readSuccess" in another function:
Some Javascript frameworks provide a utility to "bind" a function to an object, which simply means that it creates one of those little functions for you. Note that the variable "obj" will be "remembered" by those little functions, so when your handlers are called the "this" reference will be to the object that was used to call "refreshData".