views:

169

answers:

5

Hello I noticed that this simple code doesn't work the way it is supposed to work...

    function test() {
    $.ajax( {
        'url' : 'test/GameConfiguration.json',
        'dataType' : 'json',
        data : {
            a : 'aaa'
        },
        cache : false,
        method : 'get',
        timeout : 10000, //10 secs of timeout 
        success : function(data, textStatus, XMLHttpRequest) {
            console.log("success");
            if (data == null)
                console.log("it's not a real success");
        },
        error : function(XMLHttpRequest, textStatus, errorThrown) {
            console.log("error: " + textStatus);
        }
    });
}

The test has been run on localhost, I mean: I load the page, I shut down the local webserver, then I fire the request (via a simple button with onclick pointing to this function). Error doesn't ever get called, what I get is to have the success handler called and it has textStatus = "success" and data = null. I even notice that the request times out long before 10 seconds. This happens on Firefox (last version), Chrome (last version) and Safari 5. Why this? Is it due to the fact I'm working on localhost?


I forgot to tell: THE Request isn't cached. In fact both firebug and Chrome dev tools show the request to fail.


Big update

This behaviour is related to the use of localhost. In fact if I load this page from another collegue PC and before triggering the request I disconnect my PC from the network, I correctly get the error handler fired with timeout as status. I think this is a bug of jQuery. It will make me hard to test the timeout errors :(


Guys from jQuery forums say this is due to the way the network stack aborts the connection, given that the host is localhost. I tested this on Windows 7 only. If you feel like testing this on other systems and you can work out some jQuery internals, report to this post at the jQuery forums:

http://forum.jquery.com/topic/strange-and-unexpected-behaviour-of-ajax-error-and-localhost#14737000001331961

A: 

Have you checked that it isn't cached?

Alex Reitbort
This should be a comment, and since he's setting the cache option explicitly, this shouldn't happen.
Nick Craver
Yes I did, it isn't cached.
gotch4
A: 

Even if you shut down the local server, it should still be able to see the json file.. try to remove the file temporarily and see if that works.

A. M.
If I remove the file and the server is ON, of course I get a 404 and the error handler fires.If I remove the file and the server is OFF, same result.
gotch4
A: 

See the update up there

gotch4
+1  A: 

If there's a network error the success callback will be called and not the error even if it doesn't make much sense. Checkout this blog post for details. So basically what you've done by checking data == null is correct.

Darin Dimitrov
Please look at my answer and code examples. How you interpret the results? Do you think that we have a bug in jQuery?
Oleg
No, your test is wrong: you are changing the port number. This is not allowed due to Same Origin Policy restrictions: http://en.wikipedia.org/wiki/Same_origin_policy. You cannot perform AJAX queries if you change the port number.
Darin Dimitrov
You are right, that my first example should be interpret as Same "Origin Policy restrictions" error. I write new version of the code based on http://www.w3.org/TR/XMLHttpRequest, which seems to me can detect an error in both cases: "Origin Policy restrictions" or any kind on network errors. In all this cases the call of "success" handler should be interpret as an error. What do you think about this suggestion?
Oleg
+2  A: 

UPDATED: Try to replace the test (data == null) to the (XMLHttpRequest.readyState === 4 && XMLHttpRequest.status === 0).

In W3C Candidate Recommendation about XMLHttpRequest standard is described that it must exist so named "error flag" which should be used to indicates some type of network error or abortion. In case of such kind of errors the status in the XMLHttpRequest will be 0 instead of 200 ("OK"), 201 ("Created"), 304 ("Not Modified") and so on. To be exactly corresponds to http://www.w3.org/TR/XMLHttpRequest/#the-status-attribute the XMLHttpRequest.status can be 0 in case of XMLHttpRequest.readyState equal to 0 or 1 ("UNSENT" or "OPENED"). Another case is XMLHttpRequest.readyState equal to 4 ("DONE") and "error flag" is true. If we have no from these two cases the XMLHttpRequest.status must be a HTTP status code. Under http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html or http://www.w3.org/Protocols/HTTP/1.0/spec.html#Status-Codes there are no HTTP status code equal to 0. So it seems to my that you can do following

jQuery(document).ready(function () {
    $.ajax({
        type: 'GET',
        url:  'test/GameConfiguration.json',
        dataType: 'json',
        cache : false,
        success: function(data, textStatus, xhr){
            if (xhr.readyState === 4 && xhr.status === 0) {
                // if readyState is DONE (numeric value 4) then corresponds to
                // http://www.w3.org/TR/XMLHttpRequest/#dom-xmlhttprequest-done
                // "The DONE state has an associated error flag that indicates
                // some type of network error or abortion."
                // Corresponds to http://www.w3.org/TR/XMLHttpRequest/#the-status-attribute
                // If error flag it true, xhr.status is 0.
                alert('"error flag\" is true. It means that we have a network error"+
                      " or abortion (for example because of Same Origin Policy restrictions)');
            }
            else {
                alert(textStatus);
                alert(data);
            }
        },
        error: function(xhr, textStatus, errorThrown) {
            if (textStatus !== null) {
                alert("error: " + textStatus);
            } else if (errorThrown !== null) {
                alert("exception: " + errorThrown.message);
            }
            else {
                alert ("error");
            }
        }
    });
});
Oleg
Thanks, this sounds more robust. Anyway I posted all this in jQuery forums and some dev started caring about this. I even sent some debug logs and probably this thing will be fixed.
gotch4
@gotch4: I couldn't find your post in jQuery bug reports. Could you post the reference? I found some other close reports like http://dev.jquery.com/ticket/6060. It seems that the change http://dev.jquery.com/changeset/6432 which try to make a workaround for Opera was wrong implemented and work wrong now in case XMLHttpRequest.status=0 in other browsers. If you not do this. I'll recoment you to insert in your bug report the reference http://www.w3.org/TR/XMLHttpRequest/#the-status-attribute. The code of jQuery should at least follow standards and then try to implement any workaround.
Oleg