Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

XmlHttpRequest.onload not called

I'm playing around with this XmlHttpRequest thing. In some tutorials and books, it is the onload function the one that is called when the request is done. In my little experiment, this function is never called. Here's my code:

    window.onload = function() {
        var url = "http://www.google.com";
        var request = new XMLHttpRequest();


        request.onload = function() {
            var state = this.readyState;
            var responseCode = request.status;
            console.log("request.onload called. readyState: " + state + "; status: " + responseCode);

            if (state == this.DONE && responseCode == 200) {
                var responseData = this.responseText;
                alert("Success: " + responseData.length  + " chars received.");
            }
        };

        request.error = function(e) {
            console.log("request.error called. Error: " + e);
        };

        request.onreadystatechange = function(){
            console.log("request.onreadystatechange called. readyState: " + this.readyState);
        };

        request.open("GET", url);
        request.send(null);
    };

I'm testing this on the last Firefox release (just updated today). The log line in onload is never printed, and the breakpoint I set in the first line is never hit. However, the onreadystatechange function is called twice, and the http request is actually made. This is what firebug's console shows:

    request.onreadystatechange called. readyState: 1
    GET http://www.google.com/    302 Found    174ms
    request.onreadystatechange called. readyState: 4
    NS_ERROR_FAILURE: Failure
        request.send(null);

There's an error in the send line. I've tried changing it to request.send() with identical result.

At first I thought this might be the browser trying to prevent XSS, so I moved my html driver page to a Tomcat instance in my dev machine, but the result is the same.

Is this function guaranteed to be called? As I've said above, it's common to be seen in most tutorials, but on the other hand in the W3C spec page, the hello world snippet uses onreadystatechange instead:

    function processData(data) {
      // taking care of data
    }

    function handler() {
      if(this.readyState == this.DONE) {
        if(this.status == 200 &&
           this.responseXML != null &&
           this.responseXML.getElementById('test').textContent) {
          // success!
          processData(this.responseXML.getElementById('test').textContent);
          return;
        }
        // something went wrong
        processData(null);
      }
    }

    var client = new XMLHttpRequest();
    client.onreadystatechange = handler;
    client.open("GET", "unicorn.xml");
    client.send();

It checks readyState == this.DONE. DONE has the value 4, which is what I can see in my log. So if this were a XSS related issue, and the browser were preventing me to make the connection to a different domain, then why the actual connection is made and the DONE status is received???

PS: Yes, I know there are powerful libraries to do this easily, but I'm still a JavaScript noob so I'd like to understand the low level first.


UPDATE:
I've changed the URL to one inside my domain (localhost), and the error is gone but the onload function is still not being called. Tested in IE8 and does not work. Tested in Chrome and works. How's that?


UPDATE 2:
Tested again in Firefox, and now it works. Probably the old page was still cached so that's why I couldn't notice it immediatly. Still failing in IE8, I'll try to test it in a newer version.

like image 240
Mister Smith Avatar asked Feb 06 '13 11:02

Mister Smith


People also ask

What does XMLHttpRequest onload do?

The onload Property With the XMLHttpRequest object you can define a callback function to be executed when the request receives an answer.

How to call api using XMLHttpRequest?

To send an HTTP request, create an XMLHttpRequest object, open a URL, and send the request. After the transaction completes, the object will contain useful information such as the response body and the HTTP status of the result.

What is XMLHttpRequest() in JavaScript?

XMLHttpRequest (XHR) objects are used to interact with servers. You can retrieve data from a URL without having to do a full page refresh. This enables a Web page to update just part of a page without disrupting what the user is doing. XMLHttpRequest is used heavily in AJAX programming.


2 Answers

The onload handler won't be called for yet another reason, I'm adding it here just so it can be helpful to someone else referencing this page.

If the HTTP response is malformed, the onload handler will not be called either. For example, a plaintext response of 10 bytes that advertises a length of 14 in Content-Length header will not invoke the onload handler. I wasted hours on client code before I start to replace back-end units with test stubs.

like image 69
DannyNiu Avatar answered Sep 21 '22 16:09

DannyNiu


It looks like it was indeed a XSS issue and Firefox was blocking the onload call. I can't still understand why the http network request was actually being done and the onreadystatechange was being called with the DONE readyState.

I changed the URL to another one in the same domain, and now it works in Firefox (after some cache-related false attempts) and in Chrome. It still does not work in IE8, despite the official docs say it is supported. I've found this SO answer which states otherwise. It looks like the onload function is a more modern convenience method and the old way of checking the result is using onreadystatechange instead.

I guess I'll accept this answer as the solution unless a more detailed answer is provided.

like image 36
Mister Smith Avatar answered Sep 18 '22 16:09

Mister Smith