Skip to main content

jQuery ajax (jsonp) ignores a timeout and doesn"t fire the error event


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);
}
});

});



I'd like to add that this question was asked when jQuery was at version 1.4.2


Source: Tips4allCCNA FINAL EXAM

Comments

  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 cal the error handler, when there is no successful request after 10 seconds.

    I did a little blogpost on this subject as well.

    ReplyDelete
  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);
    }
    });
    });

    ReplyDelete
  3. A solution if you're stuck with jQuery 1.4:

    var timeout = 10000;
    var id = setTimeout( errorCallback, timeout );
    $.ajax({
    dataType: 'jsonp',
    success: function() {
    clearTimeout(id);
    ...
    }
    });

    ReplyDelete
  4. 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.

    ReplyDelete
  5. Seems to be resolved as of jQuery 1.5. I've tried the code above and I get the callback.

    I say "seems to be" because the documentation of the error callback for jQuery.ajax() still has the following note:


    Note: This handler is not called for cross-domain script and JSONP requests.

    ReplyDelete

Post a Comment

Popular posts from this blog

[韓日関係] 首相含む大幅な内閣改造の可能性…早ければ来月10日ごろ=韓国

div not scrolling properly with slimScroll plugin

I am using the slimScroll plugin for jQuery by Piotr Rochala Which is a great plugin for nice scrollbars on most browsers but I am stuck because I am using it for a chat box and whenever the user appends new text to the boxit does scroll using the .scrollTop() method however the plugin's scrollbar doesnt scroll with it and when the user wants to look though the chat history it will start scrolling from near the top. I have made a quick demo of my situation http://jsfiddle.net/DY9CT/2/ Does anyone know how to solve this problem?

Why does this javascript based printing cause Safari to refresh the page?

The page I am working on has a javascript function executed to print parts of the page. For some reason, printing in Safari, causes the window to somehow update. I say somehow, because it does not really refresh as in reload the page, but rather it starts the "rendering" of the page from start, i.e. scroll to top, flash animations start from 0, and so forth. The effect is reproduced by this fiddle: http://jsfiddle.net/fYmnB/ Clicking the print button and finishing or cancelling a print in Safari causes the screen to "go white" for a sec, which in my real website manifests itself as something "like" a reload. While running print button with, let's say, Firefox, just opens and closes the print dialogue without affecting the fiddle page in any way. Is there something with my way of calling the browsers print method that causes this, or how can it be explained - and preferably, avoided? P.S.: On my real site the same occurs with Chrome. In the ex