JQuery Ajax - Как обнаружить ошибку сетевого подключения при вызове Ajax

91

У меня есть код Javascript JQuery, который выполняет вызов Ajax на сервер каждые 5 минут, чтобы поддерживать сеанс сервера и сохранять пользователя в системе. Я использую $.ajax()метод в JQuery. Кажется, у этой функции есть свойство error, которое я пытаюсь использовать в случае, если интернет-соединение пользователя прерывается, чтобы скрипт 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 секунд, и это нормально. Однако, как только я отсоединяю сетевой кабель, я ничего не получаю, я ожидал, что функция ошибки будет вызвана и увидеть окно предупреждения «Сбой», но ничего не происходит.

Правильно ли я предполагаю, что функция 'error' предназначена только для кодов состояния, отличных от 200, возвращаемых с сервера? Есть ли способ обнаружить проблемы с сетевым подключением при выполнении вызова Ajax?

Воскресенье Ironfoot
источник
Вы отключили сетевой кабель клиента или сетевой кабель сервера?
Джефф Стернал,
Вы продолжаете получать уведомление об успешном завершении подключения после отключения соединения?
Wilkins
3
@Jeff - Проблема связана с потерей интернет-соединения на стороне клиента. Невероятно, но это действительно происходит, поскольку некоторые клиенты используют приложение с изворотливым беспроводным соединением, которое постоянно пропадает. Есть поговорка «Никогда не недооценивайте способность конечных пользователей находить способы взломать ваше приложение», здесь определенно звучит правдоподобно :-)
Sunday Ironfoot,
@qwertypants - Нет, при потере интернет-соединения ничего не происходит (например, при отключении кабеля). Хотя попытка $ .ajax сделана, я вижу ее в Firebug.
Воскресенье Ironfoot,
Есть ли способ установить тайм-аут для попытки подключения?
axk

Ответы:

99
// 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
источник
4
Это должен быть принятый ответ. В функции ошибки, которую вы предоставляете $ .ajax, первый параметр предоставляет всевозможную информацию о состоянии. Это произойдет, даже если вы не установите тайм-аут.
Майк Спир,
И сделать то же самое с формой ajax: <form ... data-ajax-failure="YourMethod" ...></form>и с вашим методомfunction YourMethod(XMLHttpRequest) { ..same code... }
Матье Шарбонье
1
Для получения дополнительной информации XMLHttpRequest.readyStateсм. Ajax_xmlhttprequest_response.asp
stomy
13

Вы должны просто добавить: timeout: <number of miliseconds>,где-то внутри $.ajax({}). Кроме того, cache: false,может помочь в нескольких сценариях.

$ .ajax хорошо документирован , вы должны проверить там параметры, возможно, найдете что-нибудь полезное.

Удачи!

Круле
источник
1
в Ajax есть много вещей, которые вообще не задокументированы и как-то спрятаны :(
Espanta
9

Поскольку я не могу дублировать проблему, я могу предложить только попробовать с тайм-аутом для вызова ajax. В jQuery вы можете установить его с помощью $ .ajaxSetup (и он будет глобальным для всех ваших вызовов $ .ajax) или вы можете установить его специально для своего вызова следующим образом:

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

JQuery зарегистрирует таймаут 15 секунд для вашего вызова; после этого без кода ответа http от сервера jQuery выполнит обратный вызов ошибки со значением textStatus, установленным на «тайм-аут». С этим вы можете хотя бы остановить вызов ajax, но вы не сможете отличить реальные проблемы с сетью от потери соединений.

Марко З
источник
3

В этом случае я вижу, что если я потяну за сетевой кабель клиентской машины и сделаю вызов, будет вызван обработчик успеха ajax (почему, я не знаю), а параметр данных - пустая строка. Итак, если вы исключите реальную обработку ошибок, вы можете сделать что-то вроде этого:

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

jQuery.ajax({
    ...
    success: function(data, textStatus, jqXHR) {
        if (data == "") handleError(jqXHR, "clientNetworkError", "");
    },
    error: handleError
});
Джефф
источник
1

Если вы выполняете кросс-домен, вызовите Use Jsonp. иначе ошибка не возвращается.

Свапнил Ребелло
источник
0

ИСПОЛЬЗОВАТЬ

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

};

(больше кода ниже - ЗАГРУЗИТЬ ПРИМЕР ИЗОБРАЖЕНИЯ)

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
источник
-1

вот что я сделал, чтобы предупредить пользователя в случае отказа его сети или сбоя обновления страницы:

  1. У меня есть div-тег на странице, где я помещаю текущее время и обновляю этот тег каждые 10 секунд. Это выглядит примерно так:<div id="reloadthis">22:09:10</div>

  2. В конце функции javascript, которая обновляет время в теге div, я помещаю это (после обновления времени с помощью AJAX):

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

Это оно! Вы, конечно, можете заменить часть предупреждения чем угодно. Надеюсь это поможет.

куммик
источник
-6

Вы пробовали это?

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

Это должно обрабатывать все ошибки AjaxErrors. Я нашел это здесь . Там вы также найдете возможность записать эти ошибки в консоль firebug.

MaikL80
источник