JQuery Ajax - Як виявити помилку підключення до мережі під час здійснення виклику Ajax


91

У мене є Javascript-код JQuery, який робить виклик Ajax на сервер кожні 5 хвилин, він підтримує сеанс сервера живим і підтримує вхід користувача. Я використовую $.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?


Ви відключили мережевий кабель клієнта або мережевий кабель сервера?
Джефф Стернал

Ви продовжуєте отримувати попередження про успіх після відключення підключення?
Уілкінс

3
@Jeff - Проблема спричинена втратою з’єднання з Інтернетом на кінцевому рівні. Це неймовірно, насправді це відбувається, оскільки деякі клієнти використовують додаток із хитрим бездротовим з'єднанням, яке постійно випадає. Існує приказка "Ніколи не недооцінюйте здатність кінцевих користувачів знаходити способи зламати вашу програму", це точно звучить правдою :-)
Sunday Ironfoot

@qwertypants - Ні, нічого не відбувається після втрати з’єднання з Інтернетом (наприклад, від'єднання кабелю). Хоча спроба $ .ajax зроблена, я бачу це у Firebug.
неділя Ironfoot

Чи є спосіб встановити тайм-аут для спроби з'єднання?
axk

Відповіді:


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

4
Це має бути прийнятою відповіддю. У функції помилок, яку ви надаєте $ .ajax, перший параметр забезпечує всіляку інформацію про стан. Це робиться, навіть якщо ви не встановили тайм-аут.
Mike Spear

І зробити те саме з формою 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
є багато речей, які взагалі не задокументовані в Аяксі, і якимось чином приховані :(
Еспанта,

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, встановленим на "timeout". За допомогою цього ви можете принаймні зупинити виклик 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.