Изменить страницу в середине запроса Ajax

Что произойдет, если я отправлю какой-либо запрос ajax и сразу же изменю страницу (скажем, следуйте по какой-либо ссылке) до того, как запрос вернется? Я имею в виду, я предполагаю, что объект XHR отправляет запрос на веб-сайт, но он удаляется (поскольку страница изменена) до получения ответа, поэтому где ответ должен быть отправлен?

Я задаю этот вопрос, потому что у меня возникла странная проблема с моим сайтом. У меня есть страница, которая загружает сообщения из хранилища данных через запрос Ajax. Если до завершения загрузки я нажимаю ссылку, я получаю onerror jQuery.ajax, вызываемый! Не знаю, почему это происходит.

EDIT: Это мой призыв к ajax. В нормальном случае вызывается обратный вызов успеха. Но когда я нажимаю на ссылку, вызывается обратный вызов ошибки! Я думаю о чем-то, может быть, потому, что данные должны быть отформатированы как JSON, но запрос срезается посередине, поэтому данные считаются недействительными, что приводит к тому, что jQuery вызывает обратный вызов ошибки?! Но тогда почему запросы срезаются посередине?

$.ajax({
  type: (args.rel == "async" || args.rel == "dialog") ? "GET" : "POST",
  url: href,
  dataType: "json",
  data: args.data ? args.data:{}, // send {} to ensure Content-Length header
  success: function(data){
    if (context) context.removeClass("ajax_wait");
    if (args.hideonwait) $(args.hideonwait).show();
    if (args.showonwait) $(args.showonwait).hide();
    if (spinner) remove_spinner(context, spinner);
    handle_response(args, context, target, data);
  },
  error: function(xhr, status, errorThrown){
    if (context) context.removeClass("ajax_wait");
    if (args.hideonwait) $(args.hideonwait).show();
    if (args.showonwait) $(args.showonwait).hide();
    if (spinner) remove_spinner(context, spinner);
    ajax_error(args, context,
               status + "-" + xhr.status,
               errorThrown ? errorThrown : xhr.responseText);
  }
});

Ответ 1

Трюк заключается в проверке заголовков ответов в объекте XMLHttpRequest. Если нет заголовков ответов (пустая или пустая строка, в зависимости от браузера), сервер еще не ответил. Это означает, что пользователь прервался.

$.ajax({
    url: "url-to-go-here",
    success: function() {
    },
    error: function(xhr, textStatus, errorThrown) {
        if(!isUserAborted(xhr)) {
            console.log("Ajax Error")
        }
    }
});

function isUserAborted(xhr) {
  return !xhr.getAllResponseHeaders();
}

Источник

Ответ 2

Поведение, похоже, происходит, когда пользователь оставляет страницу, любые выдающиеся аякс-запросы с 0 в качестве их статуса. jQuery интерпретирует это как ошибку, поэтому он вызывает обработчик ошибок. В обработчике ошибок вы можете вызвать ту же функцию, что и ваш обработчик успеха, если xhr.status == 0, в противном случае выполните требуемое поведение ошибки.

Ответ 3

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

Для этого вам необходимо поддерживать семафор, установить этот семафор перед тем, как запустить любой запрос, и reset он по завершении этого запроса. При щелчке по каждой ссылке (которая меняет страницу) вызывается метод, который проверяет семафор, и если он установлен, то метод дает вышеупомянутое предупреждение пользователю. Таким образом, пока запрос не завершится, пользователь не сможет изменить страницу, и ваша проблема прерывания запроса будет решена.

Надеюсь, что это ответит на вопрос.

Ответ 4

Вам не повезло. У вас не было бы обратного вызова, чтобы вернуться. Ответ Ajax будет потерян. В этом случае я бы поставил на страницу блокировщик. Это довольно распространено, чтобы предотвратить другой щелчок. Блокатор не более, чем большая маска, которая "закладывает" весь браузер. Он также может иметь значок ожидания.

Ответ 5

Мне приходилось иметь дело с одной и той же проблемой несколько дней назад.. Кажется, что это не так сложно с этим. Мы должны отличить погоду от какой-либо ошибки ajax или пользователя отменить запрос. Конечно мы не получаем конкретное событие от объекта xhr.. то почему ошибка ajax возникает с исключением... комбинация как объекта xhr, так и значения исключений мы можем решить это.

var message = '';
$('whatever').ajaxError(function(e, xhr, settings, exception) {
  // logic
   if (!xhr.status){
      if (exception=='abort'){
         message = 'User aborted AJAX request !'; 
      }
   }
}