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?


Вы отключили сетевой кабель клиента или сетевой кабель сервера?
Джефф Стернал,

Вы продолжаете получать уведомление об успешном завершении подключения после отключения соединения?
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

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


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

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

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.