Cannot access manifest-cached files with AJAX from webapp saved to Home screen in iOS devices, using jQuery.ajax()

I'm making a webapp. Some of the files that it loads contain pure, static .JSON data. I am using jQuery.ajax() (jQuery 1.5.2) with dataType:'json' and cache:true. Everything works well and all files are loaded. I have also configured the cache manifest to cache these JSON files (in addition to css , js, and images). Everything works well there too - when a user visits my site all the files that I need are cached correctly (I have applicationCache event handlers that confirm all is well). I have tested everything in Google Chrome and I can see that all files (including the JSON ones) are cached. When I disconnect from the network, everything works (the jQuery ajax calls automagically fetch the cached JSON files).

Now I am trying to test this on mobile Safari (on actual iPad and the iPhone simulator). Everything works as expected when in Safari - the pages are cached and on subsequent visits with network disconnected, the cached files are used.

However, when I add the app to the Home Screen using "add to home screen" in Safari, the app starts up and all the .js, .css, and images work correctly, BUT my Ajax calls don't! They don't access the cached .json files. For each Ajax call the XMLHttpRequest.status is 0, .statusText is error, but getAllResponseHeaders() shows the same (correct) headers as in the functional app in Safari.

I don't get this. Is this a limitation/bug in jQuery's .ajax() or what? Any help is appreciated.

Answers:

Answer

Well, I hate to have to answer my own question, but here is what I've done in case someone else runs into this problem:

Apparently, when trying to use $.ajax() in offline mode, the request successfully fetches the cached files, but it returns 0 on XHMLHttpRequest.status. Having read up on this, I have seen that a status code of 0 can be returned when the user is offline and even when requesting local files. However, a successful GET should report a status code between 200 and 300. Perhaps $.ajax() checks for a 200-300 status, otherwise the request is considered to have failed.

To get around this, I added code to my error handler for the $.ajax() request which checks the jqXHR.responseText.**length**. I know the correct number of characters in my JSON files, so if jqXHR.responseText.length is the same as this known value, I consider the request a success and continue loading the files. The only extra thing I have to do is add JSON.parse(jqXHR.responseText) in the error handler, because the data is not parsed on status code 0.

Answer

Another way to go about this (especially if you're a jQuery fan) could be to use the jQ Ajax method and force no cache:

cache:false,

Obviously, ajax will fail to load server side data while offline so why not check if user's online and if so, go ahead and fetch data:

 if(navigator.onLine) { //if user's online

    var data = 'data=' + randomVar;

    $.ajax({
        url: "url.php",  
        type: "POST",
        timeout:45000, //45 secs        
        data: data,
        cache: false,
        error: function () { alert("error: 45 secs have passed since request was sent. No data was returned - too slow internet connection or some other random error."); },
        success: function (responseText) {
            // do whatever if successful
        }
    });


} // if online

Tags

Recent Questions

Top Questions

Home Tags Terms of Service Privacy Policy DMCA Contact Us

©2020 All rights reserved.