jQuery ajax (jsonp) ignores a timeout and doesn't fire the error event
Solution 1:
jQuery 1.5 and higher have better support for error handling with JSONP requests. However, you need to use the $.ajax
method instead of $.getJSON
. For me, this works:
var req = $.ajax({
url : url,
dataType : "jsonp",
timeout : 10000
});
req.success(function() {
console.log('Yes! Success!');
});
req.error(function() {
console.log('Oh noes!');
});
The timeout seems to do the trick and call the error handler, when there is no successful request after 10 seconds.
I did a little blogpost on this subject as well.
Solution 2:
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">
</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);
}
});
});