web-dev-qa-db-de.com

Wie rufe ich eine Funktion auf 404 in einer JSON-Ajax-Anfrage mit jQuery zurück? 

Ich möchte eine Ajax-Anfrage mit Antwort in JSON stellen. Also machte ich diese Ajax-Anfrage:

$.ajax({
    url: 'http://my_url',
    dataType: "json",
    success: function(data){
      alert('success');
    },
    error: function(data){
      alert('error');
    },
    complete: function(data) {
      alert('complete')
    }})

Dieser Code funktioniert gut, aber wenn meine URL mir einen HTTP-Code 404 sendet, werden keine Rückrufe verwendet, auch nicht der vollständige Rückruf. Nach der Recherche liegt es daran, dass mein Datentyp 'json' ist, die Rückgabe also HTML ist und das JSON-Parsing fehlgeschlagen ist. Also kein Rückruf.

Haben Sie eine Lösung, um eine Rückruffunktion aufzurufen, wenn ein 404 ausgelöst wird?

BEARBEITEN: Vollständiger Rückruf, kein Rückruf ist 404. Wenn Sie eine URL mit 404 wünschen, können Sie anrufen: http://Twitter.com/status/user_timeline/jksqdlmjmsd.json?count=3&callback=jsonp1269278524295&_=1269278536697 Mit dieser URL habe ich mein Problem.

21
shingara
$.ajax({
    url: 'http://Twitter.com/status/user_timeline/jksqdlmjmsd.json?count=3&callback=jsonp1269278524295&_=1269278536697',
    dataType: "json",
    success: function(data) {
        alert('success');
    },
    error: function(data) {
        alert('error');
    },
    complete: function(xhr, data) {
        if (xhr.status != 0)
             alert('success');
        else
             alert('fail');
    }
})
19
Dustin Laine

Mit Ihrer Konfiguration verwendet jQuery jsonp , um die Daten zu transportieren. Dies funktioniert, indem dynamisch ein Skriptelement eingefügt und die URL auf den angegebenen Wert festgelegt wird. Die vom Server zurückgegebenen Daten werden dann als JavaScript ausgewertet - normalerweise wird der bereitgestellte Rückruf aufgerufen. Wenn der Server eine 404 zurückgibt, ist der Inhalt offensichtlich kein JavaScript und der Rückruf wird nie aufgerufen. Einige Browser unterstützen Fehlerbehandlungsroutinen für das Skript-Tag, die in diesen Situationen aufgerufen werden. Leider unterstützt IE dies nicht. Der beste Weg, um einen Fehler zu erkennen, ist eine Zeitüberschreitung.

In Ihrem Fall sollten Sie eine zusätzliche Option timeout angeben, mit der der Fehlerbehandler aufgerufen wird, wenn der Rückruf nicht rechtzeitig aufgerufen wurde (was bei einer 404-Antwort der Fall wäre).

$.ajax({
  url: 'http://my_url',
  timeout: 2000, // 2 seconds timeout
  dataType: "json",
  success: function(data){
    alert('success');
  },
  error: function(data){
    alert('error');
  },
  complete: function(data) {
    alert('complete')
  }
});
9
Fabian Jakobs

Wenn Sie Fehler beim Zugriff auf die Twitter-API mit Javascript und jsonp behandeln möchten, müssen Sie den Parameter suppress_response_codes in Ihre Anfrage aufnehmen. Dadurch werden alle Antworten von der Twitter-API mit einer 200 OK-Antwort beantwortet und enthalten einen Fehler. Dann müssen Sie prüfen, ob die Antwort den Parameter error enthält oder nicht.

$.ajax({
  url: "https://api.Twitter.com/1/users/show.json",
  dataType: 'jsonp',
  jsonp: "callback",
  data: {
    screen_name: "simongate1337",
    suppress_response_codes: true // <- Important part
  },
  success: function(data) {
    if(data.error) {
      console.log("ERROR: "+data.error);
    } else {
      console.log("Success, got user " + data.screen_name);
    }
  }
});
4
Simon Gate

Verwenden Sie die Option statusCode-

$.ajax({
    url: 'http://my_url',
    dataType: "json",
    statusCode: {
        404: function() {
            alert("I could not find the information you requested.");
        }
    },
    success: function(data) {
      alert('success');
    },
    error: function(data) {
      alert('error');
    },
    complete: function(data) {
      alert('complete');
    }
})
3
Peter Rader

Denken Sie nicht, dass das Problem nicht beim Datentyp liegt, sondern bei domänenübergreifenden Anfragen, die Sie nicht stellen dürfen?

Der folgende Code funktioniert wie erwartet, wenn Sie Daten von derselben Domain anfordern und nicht, wenn Sie domänenübergreifende Anfragen stellen:

function handle404(xhr){
    alert('404 not found');
}

function handleError(xhr, status, exc) {
     // 0 for cross-domain requests in FF and security exception in IE 
    alert(xhr.status);
    switch (xhr.status) {
        case 404:
            handle404(xhr);
            break;
    }
}

function dumbRequest() {
    var url = 'http://Twitter.com/status/user_timeline/jksqdlmjmsd.json?count=3&callback=jsonp1269278524295&_=1269278536697';
    url = 'http://Twitter.com/';    
    url = '/mydata.json';    
//    url = 'mydata.json';    
    $.ajax(
        {url: url,
         dataType: 'json',
         error: handleError}
    );
}
2
newtover

Ist Ihnen bewusst, dass der tatsächliche Text, obwohl der HTTP-Status 404 ist, ein gültiger JSON-Text ist? Zum Beispiel hat dieser Link den folgenden JSON:

jsonp1269278524295({"request":"/status/user_timeline/jksqdlmjmsd.json?count=3&callback=jsonp1269278524295&_=1269278536697","error":"Not found"})

Daher sollten Sie in Ihrer normalen Rückruffunktion prüfen, ob Ihre Daten die Eigenschaft error haben.

UPDATE: Obwohl der tatsächliche Inhalt der Seite ein gültiger JSON-Code ist, führt der Browser (ich habe in Firefox geprüft) ihn anscheinend nicht aus, höchstwahrscheinlich, weil es sich um einen 404 handelt. Weil jQuery hinzufügen muss Als script -Element (aufgrund des domänenübergreifenden Problems) wird sein JSONP-Wrapper niemals aufgerufen, und infolgedessen auch nicht Ihre Rückrufe.

Kurz gesagt, ich glaube nicht, dass es eine Möglichkeit gibt, damit umzugehen, ohne das Skriptelement manuell hinzuzufügen und zu überprüfen, ob Ihre vordefinierte Rückruffunktion anschließend aufgerufen wurde.

1
janmoesen

Gerade vor dem gleichen Problem, und sah eine andere Frage erwähnt, dass jQuery-JSONP (jQuery Plugin) unterstützt das Abfangen von 404-Fehlern oder wie sie beschreiben: " Fehlerbehebung bei Netzwerkausfall oder schlechtem gebildete JSON-Antworten "

Und es funktioniert perfekt :)

Hier ist mein (vereinfachter) Code zum Abrufen von Details zu einem YouTube-Video über JSONP:

$.jsonp(
{
    url: "https://gdata.youtube.com/feeds/api/videos/ee925OTFBCA",
    callbackParameter: "callback",
    data: 
    {
        alt: "jsonc-in-script",
        v: "2"
    },
    success: function(json, textStatus) 
    { 
        console.log("WEEEEEEEE!"); 
    },
    error: function(xOptions, textStatus) 
    {
        console.error(arguments);
    }
});
1
Mark

Liegt es einfach daran, dass die dataType auf "json" gesetzt ist? Wenn ja, ändern Sie es in text und werten Sie den JSON selbst aus:

$.ajax({
    url: 'http://Twitter.com/status/user_timeline/jksqdlmjmsd.json?count=3&callback=jsonp1269278524295&_=1269278536697',
    dataType: 'text',
    success: function(data, status, xmlHttp) {
        try {
            data = eval('(' + data + ')');
            alert('success');
        } catch (e) {
            alert('json parse error');
        }
    },
    error: function(xmlHttp, status, error) {
        alert('error');
    },
    complete: function(xmlHttp, status) {
        alert('complete');
    }
});
1
Matt Huggins

So gehe ich damit um. Ich überprüfe die zurückgegebenen Daten auf Fehler, bevor ich versuche, sie zu verwenden. Was unten gezeigt wird, ist nur ein Beispiel, das Sie erweitern können, um Ihren Anforderungen besser zu entsprechen. Hierbei werden auch Sitzungs-Timeouts und andere Szenarien berücksichtigt ...

Mein erster Anruf:

  $.ajax({ type: 'POST', 
    url: '../doSomething',
    data: 'my data',
    success: function(data) {
      if (HasErrors(data)) return;
      var info = eval('(' + data + ')');
      // do what you want with the info object
    },
    error: function(xmlHttpRequest) {
      ReportFailure(xmlHttpRequest);
    }
  });

Und die beiden Hilfsfunktionen:

function HasErrors(data) {
  if (data.search(/login\.aspx/i) != -1) {
    // timed out and being redirected to login page!
    top.location.href = '../login.aspx';
    return true;
  }
  if (data.search(/Internal Server Error/) != -1) {
    ShowStatusFailed('Server Error.');
    return true;
  }
  if (data.search(/Error.aspx/) != -1) {
    // being redirected to site error reporting page...
    ShowStatusFailed('Server Error. Please try again.');
    return true;
  }
  return false;
}

und

function ReportFailure(msg) {
  var text;
  if (typeof msg == 'string') {
    text = msg;
  }
  else if (typeof msg.statusText == 'string') {
    if (msg.status == 200) {
      text = msg.responseText;
    }
    else {
      text = '(' + msg.status + ') ' + msg.statusText + ': ';
      // use the Title from the error response if possible
      var matches = msg.responseText.match(/\<title\>(.*?)\<\/title\>/i);
      if (matches != null)
      { text = text + matches[1]; }
      else
      { text = text + msg.responseText; }
    }
  }
  // do something in your page to show the "text" error message
  $('#statusDisplay')
    .html('<span class="ui-icon ui-icon-alert"></span>' + text)
    .addClass('StatusError');
}
0
Glen Little

Die folgende Lösung funktioniert gut für mich :)

$.ajax({
    url: 'http://my_url',
    dataType: "json",
    success: function(data){
      alert('success');
    },
    error: function(data){
      alert('error');
    },complete: function(xhr, data) {
        if(data==="parsererror"){
             alert('404');
        }
    } 
});
0
Awan