JQuery Ajax - Erkennen eines Netzwerkverbindungsfehlers beim Tätigen eines Ajax-Anrufs

91

Ich habe Javascript JQuery-Code, der alle 5 Minuten einen Ajax-Aufruf an den Server ausführt. Er dient dazu, die Serversitzung am Leben zu erhalten und den Benutzer angemeldet zu halten. Ich verwende die $.ajax()Methode in JQuery. Diese Funktion scheint eine 'error'-Eigenschaft zu haben, die ich für den Fall verwenden möchte, dass die Internetverbindung des Benutzers unterbrochen wird, sodass das KeepAlive-Skript weiterhin ausgeführt wird. Ich verwende den folgenden Code:

var keepAliveTimeout = 1000 * 10;

function keepSessionAlive()
{
    $.ajax(
    {
        type: 'GET',
        url: 'http://www.mywebapp.com/keepAlive',
        success: function(data)
        {
            alert('Success');

            setTimeout(function()
            {
                keepSessionAlive();
            }, keepAliveTimeout);
        },
        error: function(XMLHttpRequest, textStatus, errorThrown)
        {
            alert('Failure');

            setTimeout(function()
            {
                keepSessionAlive();
            }, keepAliveTimeout);
        }
    });
}

Wenn ich es starte, wird alle 10 Sekunden in einem Warnfeld das Popup "Erfolg" auf dem Bildschirm angezeigt, was in Ordnung ist. Sobald ich jedoch das Netzwerkkabel abziehe, wird nichts angezeigt. Ich hatte erwartet, dass die Fehlerfunktion aufgerufen wird und eine Warnmeldung "Fehler" angezeigt wird, aber es passiert nichts.

Bin ich zu Recht davon ausgegangen, dass die Fehlerfunktion nur für Statuscodes gilt, die nicht vom Server zurückgegeben werden? Gibt es eine Möglichkeit, Netzwerkverbindungsprobleme beim Tätigen eines Ajax-Anrufs zu erkennen?

Sonntag Eisenfuß
quelle
Haben Sie das Netzwerkkabel des Clients oder das Netzwerkkabel des Servers abgezogen?
Jeff Sternal
Erhalten Sie nach dem Trennen der Verbindung weiterhin die Meldung "Erfolg"?
Wilkins
3
@ Jeff - Es ist der Verlust der Internetverbindung auf Client-Seite, der das Problem verursacht. Unglaublicherweise geschieht dies tatsächlich, da einige Clients die App mit einer zweifelhaften drahtlosen Verbindung verwenden, die immer wieder ausfällt. Es gibt ein Sprichwort "Unterschätze niemals die Fähigkeit von Endbenutzern, Wege zu finden, um deine Anwendung zu brechen", das hier definitiv wahr ist :-)
Sonntag Ironfoot
@qwertypants - Nein, nichts passiert, wenn die Internetverbindung unterbrochen wird (z. B. Kabel abziehen). Obwohl der $ .ajax-Versuch gemacht wird, kann ich ihn in Firebug sehen.
Sonntag Ironfoot
Gibt es eine Möglichkeit, das Zeitlimit für den Verbindungsversuch festzulegen?
Axk

Antworten:

98
// start snippet
error: function(XMLHttpRequest, textStatus, errorThrown) {
        if (XMLHttpRequest.readyState == 4) {
            // HTTP error (can be checked by XMLHttpRequest.status and XMLHttpRequest.statusText)
        }
        else if (XMLHttpRequest.readyState == 0) {
            // Network error (i.e. connection refused, access denied due to CORS, etc.)
        }
        else {
            // something weird is happening
        }
    }
//end snippet
Craneum
quelle
4
Dies sollte die akzeptierte Antwort sein. In der Fehlerfunktion, die Sie $ .ajax zur Verfügung stellen, enthält der erste Parameter alle Arten von Statusinformationen. Dies ist auch dann der Fall, wenn Sie keine Zeitüberschreitung festlegen.
Mike Spear
Und um dasselbe mit einem Ajax-Formular zu tun: <form ... data-ajax-failure="YourMethod" ...></form>und über Ihre Methodefunction YourMethod(XMLHttpRequest) { ..same code... }
Matthieu Charbonnier
1
Weitere Informationen findenXMLHttpRequest.readyState Sie unter ajax_xmlhttprequest_response.asp
stomy
13

Sie sollten nur hinzufügen: timeout: <number of miliseconds>,irgendwo innerhalb $.ajax({}). Auch cache: false,könnte in einigen Szenarien helfen.

$ .ajax ist gut dokumentiert . Sie sollten dort die Optionen überprüfen und möglicherweise etwas Nützliches finden.

Viel Glück!

Krule
quelle
1
Es gibt viele Dinge, die in Ajax überhaupt nicht dokumentiert sind und irgendwie versteckt sind :(
Espanta
9

Da ich das Problem nicht duplizieren kann, kann ich nur vorschlagen, es mit einer Zeitüberschreitung beim Ajax-Aufruf zu versuchen. In jQuery können Sie es mit $ .ajaxSetup festlegen (und es ist global für alle Ihre $ .ajax-Aufrufe) oder Sie können es speziell für Ihren Anruf wie folgt festlegen:

$.ajax({
    type: 'GET',
    url: 'http://www.mywebapp.com/keepAlive',
    timeout: 15000,
    success: function(data) {},
    error: function(XMLHttpRequest, textStatus, errorThrown) {}
})

JQuery registriert bei Ihrem Anruf eine Zeitüberschreitung von 15 Sekunden. Danach führt jQuery ohne einen http-Antwortcode vom Server den Fehlerrückruf aus, wobei der textStatus-Wert auf "timeout" gesetzt ist. Auf diese Weise können Sie zumindest den Ajax-Anruf beenden, aber Sie können die tatsächlichen Netzwerkprobleme nicht vom Verbindungsverlust unterscheiden.

Marco Z.
quelle
3

In diesem Fall sehe ich, dass, wenn ich am Netzwerkkabel des Clientcomputers ziehe und den Anruf tätige, der Ajax Success Handler aufgerufen wird (warum, ich weiß nicht) und der Datenparameter eine leere Zeichenfolge ist. Wenn Sie also die tatsächliche Fehlerbehandlung herausrechnen, können Sie Folgendes tun:

function handleError(jqXHR, textStatus, errorThrown) {
    ...
}

jQuery.ajax({
    ...
    success: function(data, textStatus, jqXHR) {
        if (data == "") handleError(jqXHR, "clientNetworkError", "");
    },
    error: handleError
});
Geoff
quelle
1

Wenn Sie domänenübergreifend arbeiten, rufen Sie Use Jsonp an. Andernfalls wird der Fehler nicht zurückgegeben.

Swapnil Rebello
quelle
0

VERWENDEN

xhr.onerror = function(e){
    if (XMLHttpRequest.readyState == 4) {
        // HTTP error (can be checked by XMLHttpRequest.status and XMLHttpRequest.statusText)
        selFoto.erroUploadFoto('Erro HTTP: '+XMLHttpRequest.statusText);
    }
    else if (XMLHttpRequest.readyState == 0) {
        // Network error (i.e. connection refused, access denied due to CORS, etc.)
        selFoto.erroUploadFoto('Erro de rede:'+XMLHttpRequest.statusText);
    }
    else {
        selFoto.erroUploadFoto('Erro desconhecido.');
    }

};

(mehr Code unten - BILD-BEISPIEL HOCHLADEN)

var selFoto = {
   foto: null,

   upload: function(){
        LoadMod.show();

        var arquivo = document.frmServico.fileupload.files[0];
        var formData = new FormData();

        if (arquivo.type.match('image.*')) {
            formData.append('upload', arquivo, arquivo.name);

            var xhr = new XMLHttpRequest();
            xhr.open('POST', 'FotoViewServlet?acao=uploadFoto', true);
            xhr.responseType = 'blob';

            xhr.onload = function(e){
                if (this.status == 200) {
                    selFoto.foto = this.response;
                    var url = window.URL || window.webkitURL;
                    document.frmServico.fotoid.src = url.createObjectURL(this.response);
                    $('#foto-id').show();
                    $('#div_upload_foto').hide();           
                    $('#div_master_upload_foto').css('background-color','transparent');
                    $('#div_master_upload_foto').css('border','0');

                    Dados.foto = document.frmServico.fotoid;
                    LoadMod.hide();
                }
                else{
                    erroUploadFoto(XMLHttpRequest.statusText);
                }

                if (XMLHttpRequest.readyState == 4) {
                     selFoto.erroUploadFoto('Erro HTTP: '+XMLHttpRequest.statusText);
                }
                else if (XMLHttpRequest.readyState == 0) {
                     selFoto.erroUploadFoto('Erro de rede:'+XMLHttpRequest.statusText);                             
                }

            };

            xhr.onerror = function(e){
            if (XMLHttpRequest.readyState == 4) {
                // HTTP error (can be checked by XMLHttpRequest.status and XMLHttpRequest.statusText)
                selFoto.erroUploadFoto('Erro HTTP: '+XMLHttpRequest.statusText);
            }
            else if (XMLHttpRequest.readyState == 0) {
                 // Network error (i.e. connection refused, access denied due to CORS, etc.)
                 selFoto.erroUploadFoto('Erro de rede:'+XMLHttpRequest.statusText);
            }
            else {
                selFoto.erroUploadFoto('Erro desconhecido.');
            }
        };

        xhr.send(formData);
     }
     else{
        selFoto.erroUploadFoto('');                         
        MyCity.mensagens.push('Selecione uma imagem.');
        MyCity.showMensagensAlerta();
     }
  }, 

  erroUploadFoto : function(mensagem) {
        selFoto.foto = null;
        $('#file-upload').val('');
        LoadMod.hide();
        MyCity.mensagens.push('Erro ao atualizar a foto. '+mensagem);
        MyCity.showMensagensAlerta();
 }
 };
MalucOJonnes
quelle
-1

Folgendes habe ich getan, um den Benutzer zu benachrichtigen, falls sein Netzwerk ausfällt oder die Seitenaktualisierung fehlschlägt:

  1. Ich habe ein Div-Tag auf der Seite, auf der ich die aktuelle Zeit eingebe und dieses Tag alle 10 Sekunden aktualisiere. Es sieht ungefähr so ​​aus:<div id="reloadthis">22:09:10</div>

  2. Am Ende der Javascript-Funktion, die die Zeit im div-Tag aktualisiert, habe ich Folgendes eingefügt (nachdem die Zeit mit AJAX aktualisiert wurde):

    var new_value = document.getElementById('reloadthis').innerHTML;
    var new_length = new_value.length;
    if(new_length<1){
        alert("NETWORK ERROR!");
    }
    

Das ist es! Sie können den Alarmteil natürlich durch alles ersetzen, was Sie wollen. Hoffe das hilft.

kummik
quelle
-6

Hast du das versucht?

$(document).ajaxError(function(){ alert('error'); }

Das sollte alle AjaxErrors behandeln. Ich habe es hier gefunden . Dort finden Sie auch die Möglichkeit, diese Fehler in Ihre Firebug-Konsole zu schreiben.

MaikL80
quelle