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

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

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

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.


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


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

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.


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

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);
    });
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.