I’ve been smashing my head against this all day – but I finally got something working consistently and reliable, so I better damn well document it. This is as good a place as any, and hopefully it will be useful to others.

I needed to make an Ajax call, so I turned to my good friend XMLHttpRequest. One wrinkle was that I needed to pass in a parameter to it… so I tried:

var test = "bar";
req = new XMLHttpRequest();
req.open("GET", myURL, true);
req.foo = test;
req.onreadystatechange = function() {
    if (this.readyState != 4)
        return;
    if (this.status == 200) {
        alert(this.foo);   // should print out "bar"
    }  
}
req.send(null);

For the most part this worked. Except every now and then… when it didn’t. Most annoyingly, it failed pretty consistently when I was trying to use it within a nested Ajax call (complicated code, don’t ask.. it’s not interesting).

I’m not sure why it doesn’t work to be honest. From my understanding, req.foo should just instantiate a new foo member variable of the XMLHttpRequest object I just created and set it to be referenced via ‘this.foo’ inside any member function. I’m guessing it’s something to do with the scoping of onreadystatechange being set to the reference of an anonymous function so the anonymous function isn’t actually part of the XMLHttpRequest object and thus doesn’t have access to its member variables. What’s frustrating is that it works most of the time. A consistent failure model would actually be more helpful here.

Anyway, enough blabbering, here’s what seemed to work for me:

var test = "bar";
req = new XMLHttpRequest();
req.open("GET", myURL, true);
req.onreadystatechange = function(foo) {
    return function() {
        if (this.readyState != 4)
            return;
        if (this.status == 200) {
            alert(foo);
        };
    }(test);
}
req.send(null);

Now that works reliably for me 100% of the time.

Tags: ,

No Trackbacks to “passing parameters to XMLHttpRequest’s onreadystatechange function”

14 Comments to “passing parameters to XMLHttpRequest’s onreadystatechange function”

  1. Jon H Says:

    I bet that in your first example, if you used:

    alert (this.parentNode.Foo)

    it would work.

    this.Foo inside the scope of the anonymous function is scoped wrong.

  2. Stephen Lau Says:

    Nope, trying to do that just got me errors that “this.parentNode” didn’t exist (or had no attributes)

  3. nico Says:

    Thanks, that really saved me from a long night of trying to figure out some hideous hack. :)

    Just out of curiosity: how on Earth did you came out with that????

  4. Stephen Lau Says:

    Glad it was helpful. :) I’m honestly not sure how I came up with it. Probably through some combination of beer, and helpful colleagues.

  5. Todd dellagio Says:

    Hey thanks for this post. I was having a very similar issue and that got resolved. Thanks lau.

  6. Scott F Says:

    Thanks a lot for your help. I was having the same scope problems.

  7. Will Says:

    Hi,

    I tried this method – no joy.

    Any ideas where I’m messing up? Thanks.

    I’m trying to pass the variable ‘url’ down to the next function.

    function getData(url) { var datatosend=”graphrequest=graphcounter1″; var req = new XMLHttpRequest(); req.open(“POST”, url, true); req.onreadystatechange = function(url) { return function() { document.getElementById(“zone1″).innerHTML = “0″; if(req.readyState == 4 && req.status == 200) { document.getElementById(“zone1″).innerHTML = req.responseText;
    setTimeout(“getData(url)”, 3000); //refresh rate for graph (ms) } }(url); };
    req.setRequestHeader(“Content-Type”, “application/x-www-form-urlencoded”); req.send(datatosend); }

  8. Krishna Says:

    var req = initRequest(url); req.onreadystatechange = function() { if (req.readyState != 4) return; if (req.status == 200 ) { //alert(flagforsubmit); flagforsubmit = true;

                loadXML(req.responseXML);                   
               }    
    
       };      
       req.open("GET", url, true);       req.send(null);
    

    if(flagforsubmit){ ///code is not executed } since the flagforsubmit is not true its is taking too much time for execute and when i click the button on which i have called the function is not working(no action) after pressing 3 /4 times the output will come,

  9. Kosta Says:

    Thank you very much for this hack. Let me avoid ugly global variables.

  10. pirhotek Says:

    you could have simply referenced req.foo, rather than this.foo, as req is still in scope inside the inner function.

  11. Chetna Says:

    i don’t think req.foo or this.foo , either is required. I used foo directly and it worked for me. I didn’t even have to pass any parameter.The point here is : You are introducing an inner function which is in the scope of the outer function.Hence, all the variables can be directly referenced.

  12. Alice Says:

    instead of this.foo you could have used ‘test’ directly!!! you are passing a value to someone who already has the value with him :)

  13. Viju Says:

    Cool trick! Thanks a tun.

  14. Peter Says:

    Thank you thank you thank you thank you thank you thank you thank you!!!!!!!!!!!!!!!!!!!

Leave a Reply


Recent posts