[javascript] JQuery Ajax-Ajax 호출시 네트워크 연결 오류를 감지하는 방법

5 분마다 서버에 Ajax 호출을 수행하는 Javascript JQuery 코드가 있습니다. 서버 세션을 활성 상태로 유지하고 사용자를 로그인 상태로 유지하는 것입니다. $.ajax()JQuery에서 메서드를 사용 하고 있습니다. 이 기능은 KeepAlive 스크립트가 계속 실행되도록 사용자의 인터넷 연결이 끊어지는 경우에 사용하려는 ‘오류’속성이있는 것 같습니다. 다음 코드를 사용하고 있습니다.

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

실행하면 10 초마다 알림창에 ‘성공’팝업이 뜨는데 괜찮습니다. 그러나 네트워크 케이블을 분리하자마자 아무것도 얻지 못했습니다. 오류 기능이 호출되고 ‘실패’경고 상자가 표시 될 것으로 예상했지만 아무 일도 일어나지 않습니다.

‘오류’기능이 서버에서 반환 된 ‘200’이 아닌 상태 코드에만 해당한다고 가정 할 때 올바른가요? Ajax 호출을 할 때 네트워크 연결 문제를 감지하는 방법이 있습니까?



답변

// 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


답변

You should just add: timeout: <number of miliseconds>, somewhere within $.ajax({}).
Also, cache: false, might help in a few scenarios.

$.ajax is well documented, you should check options there, might find something useful.

Good luck!


답변

Since I can’t duplicate the issue I can only suggest to try with a timeout on the ajax call. In jQuery you can set it with the $.ajaxSetup (and it will be global for all your $.ajax calls) or you can set it specifically for your call like this:

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

JQuery will register a 15 seconds timeout on your call; after that without an http response code from the server jQuery will execute the error callback with the textStatus value set to “timeout”. With this you can at least stop the ajax call but you won’t be able to differentiate the real network issues from the loss of connections.


답변

What I see in this case is that if I pull the client machine’s network cable and make the call, the ajax success handler is called (why, I don’t know), and the data parameter is an empty string. So if you factor out the real error handling, you can do something like this:

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

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


답변

If you are making cross domain call the Use Jsonp. else the error is not returned.


답변

USE

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

};

(more code below – 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();
 }
 };


답변

here’s what I did to alert user in case their network went down or upon page update failure:

  1. I have a div-tag on the page where I put current time and update this tag every 10 seconds. It looks something like this: <div id="reloadthis">22:09:10</div>

  2. At the end of the javascript function that updates the time in the div-tag, I put this (after time is updated with AJAX):

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

That’s it! You can replace the alert-part with anything you want, of course.
Hope this helps.