Wie kann ich bei Verwendung von JSONP den Fehler jQuery $ .getJSON (oder $ .ajax mit dem Datentyp 'jsonp') abfangen?

76

Ist es möglich, einen Fehler zu erkennen, wenn JSONP mit jQuery verwendet wird? Ich habe sowohl die $ .getJSON- als auch die $ .ajax-Methode ausprobiert, aber keiner wird den 404-Fehler abfangen, den ich teste. Folgendes habe ich versucht (denken Sie daran, dass diese alle erfolgreich funktionieren, aber ich möchte den Fall behandeln, wenn er fehlschlägt):

jQuery.ajax({
    type: "GET",
    url: handlerURL,
    dataType: "jsonp",
    success: function(results){
        alert("Success!");
    },
    error: function(XMLHttpRequest, textStatus, errorThrown){
        alert("Error");
    }
});

Und auch:

jQuery.getJSON(handlerURL + "&callback=?", 
    function(jsonResult){
        alert("Success!");
    });

Ich habe auch versucht, $ .ajaxError hinzuzufügen, aber das hat auch nicht funktioniert:

jQuery(document).ajaxError(function(event, request, settings){
   alert("Error");
});

Vielen Dank im Voraus für alle Antworten!

Andy May
quelle
Was ist falsch an der Verwendung von 'error: function () {}' ??
James
1
Es feuert nicht. (Denken Sie daran, dies ist JSONP).
Andy

Antworten:

51

Es scheint, dass JSONP-Anforderungen, die kein erfolgreiches Ergebnis zurückgeben, niemals ein Ereignis, einen Erfolg oder einen Misserfolg auslösen, und zum Guten oder Schlechten ist dies anscheinend beabsichtigt.

Nach dem Durchsuchen des Bug-Trackers gibt es einen Patch, der möglicherweise eine mögliche Lösung für einen Timeout-Rückruf darstellt. Siehe Fehlerbericht Nr. 3442 . Wenn Sie den Fehler nicht erfassen können, können Sie zumindest eine Zeitüberschreitung feststellen, nachdem Sie eine angemessene Zeit auf den Erfolg gewartet haben.

Adam Bellaire
quelle
Der Link zum Fehlerbericht Nr. 3442 ist defekt. Dies ist vielleicht der richtige Link: Ticket # 3442 (geschlossene Erweiterung: behoben)
Hippietrail
Einverstanden !!! eine Frage, obwohl ich einen JSONP-Aufruf mache und einen 404-Fehler erhalte, aber keine 406 und 401 erhalte ??? Warum ???stackoverflow.com/questions/18570486/…
Hitesh
falsche Antwort, die richtige ist die, die die Verwendung von .fail (function ()) beschreibt
jumpjack
Diese Antwort sollte nicht mehr korrekt sein (mehr?) Stackoverflow.com/a/19075701/2617354 ist der richtige Weg.
Daywalker
53

Hier ist meine ausführliche Antwort auf eine ähnliche Frage.

Hier ist der Code:

jQuery.getJSON(handlerURL + "&callback=?", 
    function(jsonResult){
        alert("Success!");
    })
.done(function() { alert('getJSON request succeeded!'); })
.fail(function(jqXHR, textStatus, errorThrown) { alert('getJSON request failed! ' + textStatus); })
.always(function() { alert('getJSON request ended!'); });
user2314737
quelle
12
Ich verstehe nicht, warum dies nicht mehr positive Stimmen hat. Auf diese Weise soll natürlich die Fehlerbehandlung erfolgen. Warum lautet die akzeptierte Antwort "Es scheint, dass JSONP-Anforderungen, die kein erfolgreiches Ergebnis zurückgeben, niemals ein Ereignis, einen Erfolg oder einen Fehler auslösen", wenn dies offensichtlich einfach nicht wahr ist? Dinge, die ich nicht verstehe.
Phil294
Nachdem ich etwas genauer gelesen habe, denke ich, dass es zu tun hat, dass 2008 die Dinge in jQuery etwas anders waren;)
Daywalker
@ Daywalker Ja, die Methoden Success / Error / Complete wurden veraltet und ab JQuery 3.0 ( api.jquery.com/jQuery.get ) entfernt
user2314737
16

JSONP-Probleme erkennen

Wenn Sie keine Abhängigkeit herunterladen möchten, können Sie den Fehlerstatus selbst erkennen. Es ist einfach.

Sie können JSONP-Fehler nur mithilfe einer Zeitüberschreitung erkennen. Wenn in einer bestimmten Zeit keine gültige Antwort eingeht, wird ein Fehler angenommen. Der Fehler könnte jedoch grundsätzlich alles sein.

Hier ist eine einfache Möglichkeit, nach Fehlern zu suchen. Verwenden Sie einfach eine successFlagge:

var success = false;

$.getJSON(url, function(json) {
    success = true;
    // ... whatever else your callback needs to do ...
});

// Set a 5-second (or however long you want) timeout to check for errors
setTimeout(function() {
    if (!success)
    {
        // Handle error accordingly
        alert("Houston, we have a problem.");
    }
}, 5000);

Wie der Fahrer in den Kommentaren erwähnt hat, können Sie stattdessen auch clearTimeout verwenden:

var errorTimeout = setTimeout(function() {
    if (!success)
    {
        // Handle error accordingly
        alert("Houston, we have a problem.");
    }
}, 5000);

$.getJSON(url, function(json) {
    clearTimeout(errorTimeout);
    // ... whatever else your callback needs to do ...
});

Warum? Weiter lesen...


So funktioniert JSONP auf den Punkt gebracht:

JSONP verwendet XMLHttpRequest nicht wie normale AJAX-Anforderungen. Stattdessen wird ein <script>Tag in die Seite eingefügt, wobei das Attribut "src" die URL der Anforderung ist. Der Inhalt der Antwort wird in eine Javascript-Funktion eingeschlossen, die dann beim Herunterladen ausgeführt wird.

Zum Beispiel.

JSONP-Anfrage: https://api.site.com/endpoint?this=that&callback=myFunc

Javascript fügt dieses Skript-Tag in das DOM ein:

<script src="https://api.site.com/endpoint?this=that&callback=myFunc"></script>

Was passiert, wenn <script>dem DOM ein Tag hinzugefügt wird? Offensichtlich wird es ausgeführt.

Angenommen, die Antwort auf diese Abfrage ergab ein JSON-Ergebnis wie:

{"answer":42}

Für den Browser ist das dasselbe wie für die Quelle eines Skripts, daher wird es ausgeführt. Aber was passiert, wenn Sie dies ausführen:

<script>{"answer":42}</script>

Naja nichts. Es ist nur ein Objekt. Es wird nicht gespeichert, gespeichert und es passiert nichts.

Aus diesem Grund verpacken JSONP-Anforderungen ihre Ergebnisse in eine Funktion. Der Server, der die JSONP-Serialisierung unterstützen muss, sieht den von callbackIhnen angegebenen Parameter und gibt diesen stattdessen zurück:

myFunc({"answer":42})

Dann wird dies stattdessen ausgeführt:

<script>myFunc({"answer":42})</script>

... was viel nützlicher ist. Irgendwo in Ihrem Code befindet sich in diesem Fall eine globale Funktion mit dem Namen myFunc:

myFunc(data)
{
    alert("The answer to life, the universe, and everything is: " + data.answer);
}

Das ist es. Das ist die "Magie" von JSONP. Dann ist es sehr einfach, eine Zeitüberschreitungsprüfung einzurichten, wie oben gezeigt. Stellen Sie die Anfrage und starten Sie unmittelbar danach eine Zeitüberschreitung. Wenn Ihr Flag nach X Sekunden noch nicht gesetzt wurde, ist die Anforderung abgelaufen.

Matt
quelle
1
Sie könnten auch verwenden jsonpFailCheck = setTimeout(...)und dann anstelle von success=trueIhnen verwendenclearTimeout(jsonpFailCheck)
iancoleman
14

Ich weiß, dass diese Frage etwas alt ist, aber ich habe keine Antwort gefunden, die eine einfache Lösung für das Problem bietet, also dachte ich, ich würde meine "einfache" Lösung teilen.

$.getJSON("example.json", function() {
      console.log( "success" );
}).fail(function() { 
      console.log( "error" ); 
}); 

Wir können einfach den .fail()Rückruf verwenden, um zu überprüfen, ob ein Fehler aufgetreten ist.

Hoffe das hilft :)

Farhan Ahmad
quelle
2
Beachten Sie, dass dies nur in Version 2.x funktioniert (die die Unterstützung für IE <= 8 eingestellt hat), nicht in 1.x
Laurens Rietveld,
@LaurensRietveld Es wird seit v1 unterstützt: api.jquery.com/jQuery.getJSON
Farhan Ahmad
3

Wenn Sie mit dem Anbieter zusammenarbeiten, können Sie einen anderen Abfragezeichenfolgenparameter als Funktion zum Rückruf senden, wenn ein Fehler auftritt.

? callback =? & error =?

Dies nennt man JSONPE, aber es ist überhaupt kein Defacto-Standard.

Der Anbieter übergibt dann Informationen an die Fehlerfunktion, um Sie bei der Diagnose zu unterstützen.

Hilft jedoch nicht bei Kommunikationsfehlern - jQuery müsste aktualisiert werden, um die Fehlerfunktion auch beim Timeout zurückzurufen, wie in der Antwort von Adam Bellaire.

delitescere
quelle
2

Scheint so, als ob das jetzt funktioniert:

jQuery(document).ajaxError(function(event, request, settings){
   alert("Error");
});
Fhansen
quelle
Nur für jquery 2.x, nicht 1.x
Laurens Rietveld
1

Ich benutze dies, um einen JSON-Fehler abzufangen

try {
   $.getJSON(ajaxURL,callback).ajaxError();
} catch(err) {
   alert("wow");
   alert("Error : "+ err);
}

Bearbeiten: Alternativ können Sie auch die Fehlermeldung erhalten. Dadurch erfahren Sie, was genau der Fehler ist. Versuchen Sie, die folgende Syntax im catch-Block zu verwenden

alert("Error : " + err);
Tomjshore
quelle
3
Wie können Sie einen asynchronen Anruf versuchen / abfangen? Der Anruf endet sofort, was den Versuch / Fang betrifft. Der Rückruf oder ein Fehler tritt später auf, lange nachdem wir den Umfang dieses Codes verlassen haben .
Gone Coding
0

Darf das funktionieren?

.complete(function(response, status) {
    if (response.status == "404")
        alert("404 Error");
    else{
        //Do something
    }   
    if(status == "error")
        alert("Error");
    else{
        //Do something
    }
});

Ich weiß nicht, wann der Status in den "Fehler" -Modus wechselt. Aber ich habe es mit 404 getestet und es hat geantwortet

Marcel
quelle
Sogar wir können den Antwortstatus auf Fehlerfunktion überprüfen. Besser können wir die Fehlerfunktion nutzen.
iamjustcoder
0

Sie können jede Fehlernummer explizit behandeln, indem Sie dieses Attribut in die Ajax-Anforderung einfügen:

statusCode: {
        404: function() {
          alert("page not found");
        }
    }

Ihr Code sollte also folgendermaßen aussehen:

jQuery.ajax({
type: "GET",
statusCode: {
        404: function() {
          alert("page not found");
        }
},
url: handlerURL,
dataType: "jsonp",
success: function(results){
    alert("Success!");
},
error: function(XMLHttpRequest, textStatus, errorThrown){
    alert("Error");
}
});

hoffe das hilft dir :)

Ghost Rider3
quelle
0

Ich stellte auch diese Antwort in Stapelüberlauf - Fehler bei der Handhabung von Anrufen getJSON

Ich weiß, es ist schon eine Weile her, dass jemand hier geantwortet hat und das Poster wahrscheinlich bereits seine Antwort entweder von hier oder von irgendwo anders erhalten hat. Ich denke jedoch, dass dieser Beitrag jedem helfen wird, der nach einer Möglichkeit sucht, Fehler und Zeitüberschreitungen zu verfolgen, während er getJSON-Anfragen ausführt. Deshalb unten meine Antwort auf die Frage

Die getJSON-Struktur lautet wie folgt (auf http://api.jqueri.com ):

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

Die meisten Leute implementieren das mit

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

Wenn sie die URL var verwenden, um einen Link zu den JSON-Daten bereitzustellen, wird das Datenend als Ort zum Hinzufügen der Daten verwendet "?callback=?" und anderer Variablen werden müssen, um die richtigen JSON-Daten zurückzugeben, und die Erfolgsfunktion als Funktion zum Verarbeiten der Daten .

Sie können jedoch die Status- und xhr-Variablen zu Ihrer Erfolgsfunktion hinzufügen. Die Statusvariable enthält eine der folgenden Zeichenfolgen: "Erfolg", "Nicht geändert", "Fehler", "Zeitüberschreitung" oder "Parsererror", und die Variable xhr enthält das zurückgegebene XMLHttpRequest-Objekt ( gefunden auf 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");
    }         
});

Auf diese Weise ist es einfach, Zeitüberschreitungen und Fehler zu verfolgen, ohne einen benutzerdefinierten Zeitüberschreitungs-Tracker implementieren zu müssen, der nach Abschluss einer Anforderung gestartet wird.

Ich hoffe, dies hilft jemandem, der noch nach einer Antwort auf diese Frage sucht.

Tom Groentjes
quelle
Entschuldigung, aber dies erzeugt mit jQuery 2.2.3 nichts.
PhilPhil