Подтвердить что ты не робот

JQuery AJAX запускает обратный вызов ошибки при выгрузке окна - как я могу отфильтровать выгрузку и только поймать реальные ошибки?

Если я перемещаюсь от страницы в середине запроса $.ajax(), он вызывает обратный вызов ошибки. Я тестировал в Safari и FF запросы GET и POST.

Одним из возможных решений было бы прервать все запросы AJAX на выгрузке страницы, но обработчик ошибок вызывается перед выгрузкой, поэтому это не представляется возможным.

Я хочу иметь возможность обрабатывать REAL-ошибки, такие как 500s изящно на стороне клиента, с вежливым предупреждением или модальным диалогом, но я не хочу, чтобы эта обработка вызывалась, когда пользователь переходит от страницы.

Как это сделать?

-

(Также странно: при переходе от страницы обработчик ошибок говорит, что параметр textStatus является "ошибкой", тот же, который он выбрасывает при получении запроса 500/bad.)

4b9b3361

Ответ 1

В обратном вызове ошибки или $. ajax у вас есть три входных аргумента:

function (XMLHttpRequest, textStatus, errorThrown) {
   this; // options for this ajax request
}

Вы можете напрямую проверить xhr.status, чтобы получить код ответа HTTP, например:

$.ajax({
  url: "test.html",
  cache: false,
  success: function(html){
    $("#results").append(html);
  },
  error: function (xhr, textStatus) {
    if (xhr.status == 500) {
      alert('Server error: '+ textStatus);
    }
  }
});

Edit: Чтобы рассказать разницу между соединением, нарушенным браузером, и случаем, когда сервер выключен (комментарий jasonmerino):

При выгрузке xhr.readyState должно быть 0, где для нечувствительного сервер xhr.readyState должен быть 4.

Ответ 2

Это трудно справиться правильно во всех ситуациях. К сожалению, во многих популярных браузерах xhr.status является тем же (0), если вызов AJAX отменяется навигацией или сервером, который не работает/не отвечает. Так что этот метод редко работает.

Вот набор очень "практических" хаков, которые я накопил, которые работают достаточно хорошо в большинстве случаев, но все же не являются пуленепробиваемыми. Идея состоит в попытке поймать события навигации и установить флаг, который проверяется в обработчике ошибок AJAX. Вот так:

var global_is_navigating = false;

$(window).on('beforeunload',function() {
    // Note: this event doesn't fire in mobile safari
    global_is_navigating = true;
});

$("a").on('click',function() {
    // Giant hack that can be helpful with mobile safari
    if( $(this).attr('href') ) {
        global_is_navigating = true;
    }
});

$(document).ajaxError(function(evt, xhr, settings) {
    // default AJAX error handler for page
    if( global_is_navigating ) {
        // AJAX call cancelled by navigation. Not a real error
        return;
    }
    // process actual AJAX error here.
});

Ответ 3

(Я бы добавил это в качестве комментария к основному ответу, но еще не набрал достаточного количества баллов, чтобы сделать это!)

Я также вижу это в FF4 и Chrome (9.0.597.107). Возможно, в другом месте, но это достаточно плохо для меня, чтобы это исправить!

Одна из вещей, которые нечетны в этой ситуации, заключается в том, что возвращается XMLHttpRequest.status === 0

Это похоже на надежный способ обнаружения этой ситуации и в моем конкретном случае прервать обработку пользовательских ошибок, отображаемую пользователю:

error: function (XMLHttpRequest, textStatus, errorThrown) {
    if (XMLHttpRequest.status === 0) return;
    // error handling here
}

Также стоит упомянуть, что в предположении, что может быть проблемой в JSON-анализе того, что браузер возвращает к вызову $.ajax(), я также попытался заменить собственный JSON.stringify на версию Douglas Crockford (https://github.com/douglascrockford/JSON-js), но это не имело значения.

Ответ 4

Обратный вызов ошибки должен получить ссылку на объект XHR, проверить код состояния, чтобы увидеть, является ли это ошибкой сервера или нет?

Ответ 5

Если вы используете функции jQuery, такие как $.get, $.post, $.ajax..., то вы можете использовать параметр text_status, чтобы проверить, какой тип сбоя:

request = $.get('test.html', function(data){
    //whatever
}).fail(function(xhr, text_status, error_thrown) {

    if(text_status!== 'abort'){
        console.warn("Error!!");
    }
});

Из jQuery docs:

jqXHR.fail(функция (jqXHR, textStatus, errorThrown) {}); Альтернативная конструкция опции обратного вызова ошибки, метод .fail() заменяет устаревший метод .error(). Обратитесь к разделу deferred.fail() для подробности реализации.