JQuery Ajax - Comment détecter une erreur de connexion réseau lors d'un appel Ajax

91

J'ai du code Javascript JQuery qui fait un appel Ajax au serveur toutes les 5 minutes, c'est pour garder la session serveur en vie et garder l'utilisateur connecté. J'utilise la $.ajax()méthode dans JQuery. Cette fonction semble avoir une propriété «erreur» que j'essaie d'utiliser dans le cas où la connexion Internet de l'utilisateur tombe en panne afin que le script KeepAlive continue de fonctionner. J'utilise le code suivant:

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

Lorsque je l'exécute, j'obtiens une fenêtre contextuelle `` Succès '' à l'écran dans une boîte d'alerte toutes les 10 secondes, ce qui est bien. Cependant, dès que je débranche le câble réseau, je n'obtiens rien, je m'attendais à ce que la fonction d'erreur soit appelée et voit une boîte d'alerte «Échec», mais rien ne se passe.

Ai-je raison de supposer que la fonction «erreur» concerne uniquement les codes d'état non «200» renvoyés par le serveur? Existe-t-il un moyen de détecter les problèmes de connexion réseau lors d'un appel Ajax?

Dimanche Ironfoot
la source
Avez-vous débranché le câble réseau du client ou le câble réseau du serveur?
Jeff Sternal
Continuez-vous à recevoir l'alerte «succès» après avoir débranché votre connexion?
Wilkins
3
@Jeff - C'est la perte de connexion Internet du côté client qui cause le problème. Incroyablement, cela se produit car certains clients utilisent l'application avec une connexion sans fil douteuse qui ne cesse de tomber. Il y a un dicton "Ne sous-estimez jamais la capacité des utilisateurs finaux à trouver des moyens de casser votre application", sonne définitivement vrai ici :-)
Sunday Ironfoot
@qwertypants - Non, rien ne se passe une fois la connexion Internet perdue (par exemple, débrancher le câble). Bien que la tentative $ .ajax soit faite, je peux la voir dans Firebug.
Dimanche Ironfoot
Existe-t-il un moyen de définir le délai d'expiration de la tentative de connexion?
axk

Réponses:

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
la source
4
Cela devrait être la réponse acceptée. Dans la fonction d'erreur que vous fournissez à $ .ajax, le premier paramètre fournit toutes sortes d'informations d'état. Il le fait même si vous ne définissez pas de délai.
Mike Spear
Et faire de même avec un formulaire ajax: <form ... data-ajax-failure="YourMethod" ...></form>et sur votre méthodefunction YourMethod(XMLHttpRequest) { ..same code... }
Matthieu Charbonnier
1
Pour plus d' informations XMLHttpRequest.readyStatevoir ajax_xmlhttprequest_response.asp
Stomy
13

Vous devez simplement ajouter: timeout: <number of miliseconds>,quelque part à l'intérieur $.ajax({}). Peut également cache: false,aider dans quelques scénarios.

$ .ajax est bien documenté , vous devriez y vérifier les options, vous pourriez trouver quelque chose d'utile.

Bonne chance!

Krule
la source
1
il y a beaucoup de choses qui ne sont pas du tout documentées à Ajax et qui sont en quelque sorte cachées :(
Espanta
9

Comme je ne peux pas dupliquer le problème, je ne peux que suggérer d'essayer avec un délai d'expiration sur l'appel ajax. Dans jQuery, vous pouvez le définir avec $ .ajaxSetup (et il sera global pour tous vos appels $ .ajax) ou vous pouvez le définir spécifiquement pour votre appel comme ceci:

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

JQuery enregistrera un délai de 15 secondes pour votre appel; après cela, sans code de réponse http du serveur, jQuery exécutera le rappel d'erreur avec la valeur textStatus définie sur "timeout". Avec cela, vous pouvez au moins arrêter l'appel ajax, mais vous ne pourrez pas différencier les vrais problèmes de réseau de la perte de connexions.

Marco Z
la source
3

Ce que je vois dans ce cas, c'est que si je tire le câble réseau de la machine cliente et que j'effectue l'appel, le gestionnaire de succès ajax est appelé (pourquoi, je ne sais pas) et le paramètre de données est une chaîne vide. Donc, si vous prenez en compte la vraie gestion des erreurs, vous pouvez faire quelque chose comme ceci:

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

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

Si vous effectuez un appel interdomaine, utilisez Jsonp. sinon l'erreur n'est pas renvoyée.

Swapnil Rebello
la source
0

UTILISATION

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

};

(plus de code ci-dessous - UPLOAD IMAGE EXAMPLE)

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
la source
-1

voici ce que j'ai fait pour alerter l'utilisateur en cas de panne de son réseau ou d'échec de la mise à jour de la page:

  1. J'ai une balise div sur la page où je mets l'heure actuelle et je mets à jour cette balise toutes les 10 secondes. Cela ressemble à quelque chose comme ceci:<div id="reloadthis">22:09:10</div>

  2. À la fin de la fonction javascript qui met à jour l'heure dans la balise div, je mets ceci (après la mise à jour du temps avec AJAX):

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

C'est tout! Vous pouvez bien sûr remplacer la partie d'alerte par tout ce que vous voulez. J'espère que cela t'aides.

kummik
la source
-6

Avez-vous essayé cela?

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

Cela devrait gérer tous les AjaxErrors. Je l'ai trouvé ici . Vous y trouverez également une possibilité d'écrire ces erreurs sur votre console Firebug.

MaikL80
la source