89 votes

jQuery ajax (jsonp) ignore un délai d'expiration et ne déclenche pas l'événement d'erreur

Pour ajouter un peu de base de la gestion d'erreur, je voulais réécrire une partie du code utilisé jQuery $.getJSON à tirer dans certaines photos provenant de Flickr. La raison pour cela est que $.getJSON ne fournit pas d'erreur de manipulation ou de travailler avec des délais d'attente.

Puisque $.getJSON est juste un wrapper autour de $.ajax, j'ai décidé de réécrire la chose et surprise, surprise, il fonctionne parfaitement.

Maintenant, le plaisir commence. Quand j'ai délibérément causer une erreur 404 (en changeant l'URL) ou le réseau de délai d'attente (en n'étant pas connecté à l'interwebs), l'événement d'erreur n'est pas le feu, à tous. Je suis à une perte quant à ce que je fais mal. L'aide est très apprécié.

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

});

Je tiens à ajouter que cette question a été posée lors de jQuery a été à la version 1.4.2

86voto

Husky Points 2221

JQuery 1.5 et versions supérieures prennent mieux en charge la gestion des erreurs avec les requêtes JSONP. Cependant, vous devez utiliser la méthode $.ajax au lieu de $.getJSON . Pour moi, cela fonctionne:

 var req = $.ajax({
    url : url,
    dataType : "jsonp",
    timeout : 10000
});

req.success(function() {
    console.log('Yes! Success!');
});

req.error(function() {
    console.log('Oh noes!');
});
 

Le délai d'attente semble faire l'affaire et appeler le gestionnaire d'erreurs lorsqu'il n'y a pas de demande réussie après 10 secondes.

J'ai également publié un petit article sur ce sujet.

67voto

Jose Basilio Points 29215

C'est une limitation connue avec le natif jsonp mise en œuvre en jQuery. Le texte ci-dessous est d' IBM DeveloperWorks

JSONP est une technique très puissante pour la construction des mashups, mais, malheureusement, ce n'est pas une panacée pour tous vos inter-domaine des besoins de communication. Il a quelques inconvénients qui doivent être pris sérieusement en considération avant commettre des ressources de développement. D'abord et avant tout, il n'y a pas d'erreur la manipulation pour JSONP appels. Si l' script dynamique d'insertion de travaux, vous obtenez de l'appelé; si non, rien ne se passe. Il vient échoue silencieusement. Par exemple, vous n'êtes pas en mesure de rattraper une erreur 404 à partir du serveur. Et vous ne pouvez pas annuler ou de le redémarrage de la demande. Vous pouvez, cependant, délai d'attente après une attente raisonnable quantité de temps. (Avenir de jQuery les versions peuvent avoir une fonction pour annuler JSONP demandes.)

Cependant, il ya une jsonp plug-in disponible sur GoogleCode qui offre un soutien pour la gestion des erreurs. Pour commencer, il suffit d'apporter les modifications suivantes à votre code.

Vous pouvez soit le télécharger, ou tout simplement ajouter un script de référence pour le plug-in.

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

Modifiez ensuite votre appel ajax comme indiqué ci-dessous:

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

12voto

Rob De Almeida Points 131

Une solution si vous êtes bloqué avec jQuery 1.4:

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

8voto

Marc Points 91

Cela peut être une limitation "connue" de jQuery; cependant, cela ne semble pas être bien documenté. Aujourd'hui, j'ai passé environ 4 heures à essayer de comprendre pourquoi mon temps mort ne fonctionnait pas.

Je suis passé à jquery.jsonp et cela a fonctionné comme un charme. Je vous remercie.

2voto

Peter Tate Points 1694

Semble être résolu à partir de jQuery 1.5. J'ai essayé le code ci-dessus et je reçois le rappel.

Je dis "semble être" parce que la documentation du rappel d'erreur pour jQuery.ajax () a toujours la note suivante:

Remarque: Ce gestionnaire n'est pas appelé pour les requêtes de script interdomaine et JSONP.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X