views:

169

answers:

3

I'm writing a small ajax class for personal use. In the class, I have a "post" method for sending post requests. The post method has a callback parameter. In the onreadystatechange propperty, I need to call the callback method.

Something like this:

this.requestObject.onreadystatechange = function() {
    callback(this.responseText); 
}

However, I can't access the callback variable from within the anonomous function. How can I bring the callback variable into the scope of the onreadystatechange anonomous function?

edit:

Here's the full code so far:

function request()
{
    this.initialize = function(errorHandeler)
    {
        try {
            try {
                this.requestObject = new XDomainRequest();
            } catch(e) {
                try {
                    this.requestObject = new XMLHttpRequest();
                } catch (e) {
                    try {
                        this.requestObject = new ActiveXObject("Msxml2.XMLHTTP"); //newer versions of IE5+
                    } catch (e) {
                        this.requestObject = new ActiveXObject("Microsoft.XMLHTTP"); //older versions of IE5+
                    }
                }
            } 
        } catch(e) {
            errorHandeler();
        }
    }

    this.post = function(url,data,callback)
    {
        var response;var escapedData = "";
        if (typeof data == 'object') {
            for (i in data) {
                escapedData += escape(i)+'='+escape(data[i])+'&';
            }
            escapedData = escapedData.substr(0,escapedData.length-1);
        } else {
            escapedData = escape(data);
        }
        this.requestObject.open('post',url,true);
        this.requestObject.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
        this.requestObject.setRequestHeader("Content-length", data.length);
        this.requestObject.setRequestHeader("Connection", "close");
        this.requestObject.onreadystatechange = function()
        {
            if (this.readyState == 4) {
                // call callback function
            }
        }
        this.requestObject.send(data);
    }
}
A: 
var that = this;

Then use that instead of this inside the anonymous function.

David Dorward
After re-reading the question, I don't think he is having problems with `this`, the problem seems to access the `callback` identifier...
CMS
`this` is correct in this case - to know more we need to see more code
Sean Kinsey
I updated the question with the code.
Hussain
A: 

If callback is a variable in the containing function, it should be in scope. If it is not a variable, but is in scope in in the containing function, you may have to do something like

var cb = callback;
var xhrRequest = this;

then

cb(xhrRequest.responseText);
rob
This doesn't change anything at all, it just creates new references in the same scope.
Sean Kinsey
+3  A: 

Just pass the callback function together with the rest of the arguments

this.post = function(url, data, callback) {
    ...
    this.requestObject.onreadystatechange = function() {
        if (this.readyState == 4) {
            callback(this.responseText);
        }
    };
    ...
}

And then

foo.post("foo.html", {foo:"bar"}, function(result){
    alert(result);
});

By the way, this is a better way to convert the data into a proper string

var q = [];
for (var key in data) {
    if (data.hasOwnProperty(key)) {
        q.push(key + "=" + encodeURIComponent(data[key]));
    }
}
data = q.join("&"); //data can now be passed to .send()

encodeURIComponent is the proper function to use here as encode will not escape data properly

If you want to get a ready made function for all of this you can take a look here http://github.com/oyvindkinsey/easyXDM/blob/master/src/easyXDM.js#L358

Sean Kinsey
Thanks, that worked.A few questions.1. Why use hasOwnPropperty if key already refers to the propperty?2. Doesn't the key need to be encoded as well?Thanks again.
Hussain
1), in case some property was inherited through the prototype chain 2) only if you use keys with non-ascii values, spaces, apostrophes etc. Do you?
Sean Kinsey
Thanks, got it.
Hussain