Gestion des erreurs dans les appels getJSON

192

Comment gérer les erreurs dans un appel getJSON? Im essayant de référencer un service de script inter-domaines en utilisant jsonp, comment enregistrer une méthode d'erreur?

Ajay
la source
Ajay, pourquoi ne pas envisager de marquer la bonne réponse?
Ionică Bizău
@ IonicăBizău L'a marqué maintenant. J'ai juste perdu de vue cela pendant un moment. La réponse principale ne parle pas de JSONP. Comme l'a souligné Ben Shelock, il n'y a pas de gestionnaire d'erreurs pris en charge, c'est ce que je crois ..
Ajay

Réponses:

277

$.getJSON() est une sorte d'abstraction d'un appel AJAX normal où vous auriez à dire que vous voulez une réponse codée JSON.

$.ajax({
  url: url,
  dataType: 'json',
  data: data,
  success: callback
});

Vous pouvez gérer les erreurs de deux manières: de manière générique (en configurant vos appels AJAX avant de les appeler) ou spécifiquement (avec une chaîne de méthodes).

«générique» serait quelque chose comme:

$.ajaxSetup({
      "error":function() { alert("error");  }
});

Et la manière `` spécifique '':

$.getJSON("example.json", function() {
  alert("success");
})
.success(function() { alert("second success"); })
.error(function() { alert("error"); })
.complete(function() { alert("complete"); });
Luciano Costa
la source
Non! Vous pouvez y aller comme bon vous semble. Consultez la documentation pour obtenir une aide plus détaillée: http://api.jquery.com/jQuery.ajax
Luciano Costa
5
Notez que cela nécessite jQuery 1.5+ (essayait de le faire fonctionner avec jQuery 1.3 et se demandait pourquoi il se plaignait d'une méthode invalide :-)
kenyee
24
L'OP pose des questions spécifiquement sur le cross-site JSONPcar il semble que getJSONdans ce cas, il n'appelle pas la error()fonction. J'ai le même problème. Je suppose que cela a à voir avec la façon dont JSONPest géré totalement différent des AJAXappels normaux jQuerymalgré la getJSONgestion des deux. JSONse fait avec un XMLHTTPRequestobjet mais JSONPse fait en ajoutant dynamiquement une <script>balise à la page HEAD.
hippietrail
3
Le document jQuery indique "Remarque: ce gestionnaire n'est pas appelé pour les requêtes de script inter-domaines et JSONP." api.jquery.com/jQuery.ajax > erreur
OneWorld
10
"Les méthodes de rappel jqXHR.success (), jqXHR.error () et jqXHR.complete () introduites dans jQuery 1.5 sont obsolètes à partir de jQuery 1.8. Pour préparer votre code en vue de sa suppression éventuelle, utilisez jqXHR.done (), jqXHR .fail () et jqXHR.always () à la place. "
Skorunka František
86

Quelqu'un donne ces points à Luciano :) Je viens de tester sa réponse - j'avais une question similaire - et j'ai parfaitement fonctionné ...

J'ajoute même mes 50 cents:

.error(function(jqXHR, textStatus, errorThrown) {
        console.log("error " + textStatus);
        console.log("incoming Text " + jqXHR.responseText);
    })
frenetix
la source
3
Était-ce avec JSONP intersite ou avec le même site JSON?
hippietrail
28
Bonne réponse! Juste une note à propos de .error: il deviendra obsolète dans jQuery 1.8, alors utilisez .fail
Anatoly Mironov
73

Voici mon ajout.

De http://www.learnjavascript.co.uk/jq/reference/ajax/getjson.html et de la source officielle

" Les méthodes de rappel jqXHR.success (), jqXHR.error () et jqXHR.complete () introduites dans jQuery 1.5 sont obsolètes à partir de jQuery 1.8. Pour préparer votre code en vue de sa suppression éventuelle, utilisez jqXHR.done (), jqXHR .fail () et jqXHR.always () à la place. "

Je l'ai fait et voici l'extrait de code mis à jour de Luciano:

$.getJSON("example.json", function() {
  alert("success");
})
.done(function() { alert('getJSON request succeeded!'); })
.fail(function() { alert('getJSON request failed! '); })
.always(function() { alert('getJSON request ended!'); });

Et avec la description de l'erreur et l'affichage de toutes les données json sous forme de chaîne:

$.getJSON("example.json", function(data) {
  alert(JSON.stringify(data));
})
.done(function() { alert('getJSON request succeeded!'); })
.fail(function(jqXHR, textStatus, errorThrown) { alert('getJSON request failed! ' + textStatus); })
.always(function() { alert('getJSON request ended!'); });

Si vous n'aimez pas les alertes, remplacez-les par console.log

$.getJSON("example.json", function(data) {
  console.log(JSON.stringify(data));
})
.done(function() { console.log('getJSON request succeeded!'); })
.fail(function(jqXHR, textStatus, errorThrown) { console.log('getJSON request failed! ' + textStatus); })
.always(function() { console.log('getJSON request ended!'); });
utilisateur2314737
la source
quel est l'ordre chronologique de done, fail, always et le code dans getJSON?
TheLogicGuy
Remarque: console.log n'est pas implémenté dans les anciens navigateurs comme IE7! Juste au cas où vous l'utiliseriez!
MadMad666
12

Je sais que cela fait un moment que quelqu'un n'a pas répondu ici et que l'affiche a probablement déjà reçu sa réponse d'ici ou d'ailleurs. Je pense cependant que cet article aidera tous ceux qui recherchent un moyen de suivre les erreurs et les délais d'attente tout en effectuant des requêtes getJSON. Donc ci-dessous ma réponse à la question

La structure getJSON est la suivante (disponible sur http://api.jqueri.com ):

$(selector).getJSON(url,data,success(data,status,xhr))

la plupart des gens implémentent cela en utilisant

$.getJSON(url, datatosend, function(data){
    //do something with the data
});

où ils utilisent l'url var pour fournir un lien vers les données JSON, le datatosend comme un endroit pour ajouter les "?callback=?"variables et d'autres qui doivent être envoyées pour obtenir les données JSON correctes renvoyées, et la fonction de succès en tant que fonction de traitement des données .

Vous pouvez cependant ajouter les variables status et xhr dans votre fonction de réussite. La variable status contient l'une des chaînes suivantes: "success", "notmodified", "error", "timeout" ou "parsererror", et la variable xhr contient l'objet XMLHttpRequest renvoyé ( trouvé sur w3schools )

$.getJSON(url, datatosend, function(data, status, xhr){
    if (status == "success"){
        //do something with the data
    }else if (status == "timeout"){
        alert("Something is wrong with the connection");
    }else if (status == "error" || status == "parsererror" ){
        alert("An error occured");
    }else{
        alert("datatosend did not change");
    }         
});

De cette façon, il est facile de suivre les délais d'expiration et les erreurs sans avoir à implémenter un suivi de délai d'expiration personnalisé qui est démarré une fois qu'une demande est effectuée.

J'espère que cela aide quelqu'un qui cherche toujours une réponse à cette question.

Tom Groentjes
la source
2
Cela ne marche pas. Le callback "success", comme son nom l'indique, n'est appelé qu'en cas de succès. (Donc je ne sais pas à quoi sert le paramètre "status" ...)
jwelsh
4

$.getJSON("example.json", function() {
  alert("success");
})
.success(function() { alert("second success"); })
.error(function() { alert("error"); })

Il est corrigé dans jQuery 2.x; Dans jQuery 1.x, vous n'obtiendrez jamais de rappel d'erreur

Pavlo O.
la source
1

J'ai été confronté à ce même problème, mais plutôt que de créer des rappels pour une demande ayant échoué, j'ai simplement renvoyé une erreur avec l'objet de données json.

Si possible, cela semble être la solution la plus simple. Voici un exemple du code Python que j'ai utilisé. (Utilisation de Flask, jsonify f de Flask et SQLAlchemy)

try:
    snip = Snip.query.filter_by(user_id=current_user.get_id(), id=snip_id).first()
    db.session.delete(snip)
    db.session.commit()
    return jsonify(success=True)
except Exception, e:
    logging.debug(e)
    return jsonify(error="Sorry, we couldn't delete that clip.")

Ensuite, vous pouvez vérifier Javascript comme ceci;

$.getJSON('/ajax/deleteSnip/' + data_id,
    function(data){
    console.log(data);
    if (data.success === true) {
       console.log("successfully deleted snip");
       $('.snippet[data-id="' + data_id + '"]').slideUp();
    }
    else {
       //only shows if the data object was returned
    }
});
Nick Woodhams
la source
Cela convient aux erreurs qui se produisent au sein du serveur, mais il ne capture pas lorsque l'appel ne peut pas atteindre le serveur ou s'il y a une erreur levée avant qu'il n'atteigne le code du serveur, par exemple si un utilisateur MVC n'est plus authentifié.
Lee Oades
1

Pourquoi pas

getJSON('get.php',{cmd:"1", typeID:$('#typesSelect')},function(data) {
    // ...
});

function getJSON(url,params,callback) {
    return $.getJSON(url,params,callback)
        .fail(function(jqXMLHttpRequest,textStatus,errorThrown) {
            console.dir(jqXMLHttpRequest);
            alert('Ajax data request failed: "'+textStatus+':'+errorThrown+'" - see javascript console for details.');
        })
}

??

Pour plus de détails sur la .fail()méthode utilisée (jQuery 1.5+), voir http://api.jquery.com/jQuery.ajax/#jqXHR

Puisque le jqXHRest retourné par la fonction, un chaînage comme

$.when(getJSON(...)).then(function() { ... });

est possible.

phil294
la source
0

Dans certains cas, vous pouvez rencontrer un problème de synchronisation avec cette méthode. J'ai écrit l'appel de rappel dans une setTimeoutfonction, et cela a fonctionné de manière synchrone très bien =)

PAR EXEMPLE:

function obterJson(callback) {


    jqxhr = $.getJSON(window.location.href + "js/data.json", function(data) {

    setTimeout(function(){
        callback(data);
    },0);
}
Alex Alonso
la source
0

C'est un fil assez ancien, mais il apparaît dans la recherche Google, alors j'ai pensé ajouter une réponse jQuery 3 en utilisant des promesses. Cet extrait montre également:

  • Vous n'avez plus besoin de passer à $ .ajax pour passer votre jeton porteur
  • Utilise .then () pour vous assurer que vous pouvez traiter de manière synchrone tout résultat (je rencontrais ce problème .always () rappel de rappel trop tôt - même si je ne suis pas sûr que ce soit vrai à 100%)
  • J'utilise .always () pour simplement montrer le résultat, qu'il soit positif ou négatif
  • Dans la fonction .always (), je mets à jour deux cibles avec le code d'état HTTP et le corps du message

L'extrait de code est:

    $.getJSON({
         url: "https://myurl.com/api",
         headers: { "Authorization": "Bearer " + user.access_token}
    }).then().always(   function (data, textStatus) {
        $("#txtAPIStatus").html(data.status);
        $("#txtAPIValue").html(data.responseText);
    });
D'Orbonia
la source