tags:

views:

4411

answers:

2

Hey fellow jQuery lovers,

To add some basic error handling, I wanted to rewrite a piece of code that used jQuery's $.getJSON to pull in some photo's from Flickr. The reason for doing this is that $.getJSON doesn't provide error handling or work with timeouts.

Since $.getJSON is just a wrapper around $.ajax I decided to rewrite the thing and surprise surprise, it works flawlessly.

Now the fun starts though. When I deliberately cause a 404 (by changing the URL) or cause the network to timeout (by not being hooked up to the interwebs), the error event doesn't fire, at all. I'm at a loss as to what I'm doing wrong. Help is much appreciated.

Here's the code:

$(document).ready(function(){

    // var jsonFeed = "http://api.flickr.com/services/feeds/photos_public.gne"; // correct URL
    var jsonFeed = "http://api.flickr.com/services/feeds/photos_public.gne_______"; // this should throw a 404

    $.ajax({
        url: jsonFeed,
        data: { "lang" : "en-us",
                "format" : "json",
                "tags" : "sunset"
        },
        dataType: "jsonp",
        jsonp: "jsoncallback",
        timeout: 5000,
        success: function(data, status){
            $.each(data.items, function(i,item){
                $("<img>").attr("src", (item.media.m).replace("_m.","_s."))
                          .attr("alt", item.title)
                          .appendTo("ul#flickr")
                          .wrap("<li><a href=\"" + item.link + "\"></a></li>");
                if (i == 9) return false;
            });
        },
        error: function(XHR, textStatus, errorThrown){
            alert("ERREUR: " + textStatus);
            alert("ERREUR: " + errorThrown);
        }
    });

});
+18  A: 

This is a known limitation with the native jsonp implementation in jQuery. The text below is from IBM DeveloperWorks

JSONP is a very powerful technique for building mashups, but, unfortunately, it is not a cure-all for all of your cross-domain communication needs. It has some drawbacks that must be taken into serious consideration before committing development resources. First and foremost, there is no error handling for JSONP calls. If the dynamic script insertion works, you get called; if not, nothing happens. It just fails silently. For example, you are not able to catch a 404 error from the server. Nor can you cancel or restart the request. You can, however, timeout after waiting a reasonable amount of time. (Future jQuery versions may have an abort feature for JSONP requests.)

However there's a jsonp plug-in available on GoogleCode that provides support for error handling. To get started, just make the following changes to your code.

You can either download it, or just add a script reference to the plug-in.

<script type="text/javascript" 
     src="http://jquery-jsonp.googlecode.com/files/jquery.jsonp-1.0.4.min.js"&gt;
</script>

Then modify your ajax call as shown below:

$(function(){
    //var jsonFeed = "http://api.flickr.com/services/feeds/photos_public.gne"; // correct URL
    var jsonFeed = "http://api.flickr.com/services/feeds/photos_public.gne_______"; // this should throw a 404  
    $.jsonp({
        url: jsonFeed,
        data: { "lang" : "en-us",
                "format" : "json",
                "tags" : "sunset"
        },
        dataType: "jsonp",
     callbackParameter: "jsoncallback",
        timeout: 5000,
        success: function(data, status){
            $.each(data.items, function(i,item){
                $("<img>").attr("src", (item.media.m).replace("_m.","_s."))
                          .attr("alt", item.title)
                          .appendTo("ul#flickr")
                          .wrap("<li><a href=\"" + item.link + "\"></a></li>");
                if (i == 9) return false;
            });
        },
        error: function(XHR, textStatus, errorThrown){
            alert("ERREUR: " + textStatus);
            alert("ERREUR: " + errorThrown);
        }
    });
});
Jose Basilio
Thanks for you answer José! The limited implementation of native jsonp in jQuery was the reason I went for $.ajax instead. However, it seems then that the problem isn't that $.getJSON is a wrapper around $.ajax but the dataType: jsonp. Is that correct?
Matijs
That's exactly right.
Jose Basilio
Did you try this out? did it work for you? If so, please accept my answer.
Jose Basilio
Haven't had time until today. It doesn't work however. I'm getting an error, but that's about it. I don't know what error as errorThrown is undefined.For now I'll stick with $.ajax and the lack of error messages. Javascript is an extra layer on top of the webpage for me. If Flickr is down or throwing error messages, we'll just have to live with it for now :) Thanks for your suggestion.
Matijs
So basically José's suggestion using the jsonp plugin should, if done correctly, work. For now however I'll stick with the basic json wrapper for jQuery.
Matijs
This worked brilliantly for me once I had hit the wall with the built-in limitations of jsonp's error handling
Jeremy Frey
Another developer saved by this tip. Thanks!
chester
A: 

This may be a "known" limitation of jQuery; however, it does not seem to be well documented. I spent about 4 hours today trying to understand why my timeout was not working.

I switched to jquery.jsonp and it worked liked a charm. Thank you.

Marc