Есть ли способ заставить Internet Explorer не ждать, пока запрос AJAX завершится, прежде чем перейти по ссылке? - PullRequest
3 голосов
/ 12 октября 2010

У меня есть html-страница, которая отображает некоторую базовую информацию об учетной записи и запускает длительный запрос jQuery AJAX для получения более подробных данных. Во время выполнения запроса Ajax пользователь может нажать кнопку с событием onclick, чтобы перейти на новую страницу, используя location.assign.

К сожалению, если кнопка нажата до того, как запрос ajax завершится, ничего не произойдет, пока запрос ajax не будет завершен. Это проблема с живым сервером. Я хочу, чтобы пользователь мог сразу уйти. FF и Chrome ведут себя лучше, но поскольку это приложение для корпоративной интрасети, на самом деле это не вариант.

Следующий код похож на страницу, о которой идет речь:

<html>
    <head>
        <script src="/js/jquery-1.3.2.min.js" type="text/javascript"> </script>

        <script type="text/javascript">
<!--
    $(function () {
        jQuery.ajax({
            type: 'GET',
            url: '/long-running-partial-html-ajax-endpoint',
            success: function (result) {
                $('#detail').html(result); });
            },
            error: function (xmlHttpRequest, textStatus, errorThrown) {
                $('#detail').html('Failed to load additional information:<br />' + textStatus + '<br />' + errorThrown);
            }
        });
    });
//-->
        </script>
    </head>
    <body>
        <h2>Account Information</h2>
        <div>Some basic details here</div>
        <div><button onclick="location.assign(&quot;/somewhere-else&quot;)" type="button">Go somewhere else now</button></div>
        <div id="detail">
            <img src="/ajax-loading-animation.gif" alt="Loading ..." />
            Loading ...
        </div>
    </body>
</html>

Вещи, которые я уже пробовал в отладчике (не в прямом эфире):

  • с использованием простой anchor вместо скриптовой кнопки
  • с использованием xhr.abort() до location.assign
  • положите alert s вокруг location.assign, чтобы убедиться, что код выполняется, когда ожидается

Замечание:

  • IE перестает анимировать gif, как только нажимается кнопка.
  • FF / Chrome должен автоматически прервать запрос ajax, так как событие jQuery ajax error сработало

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

Ответы [ 2 ]

0 голосов
/ 24 января 2011

Я закончил выполнение долгосрочной задачи в отдельном потоке на сервере.Затем ajax-вызов просто повторяет вызов, чтобы проверить, готов ли ответ.Таким образом, каждый ajax-запрос очень короткий.

Мое решение подходит для приложений в интрасети, но, вероятно, его нужно будет сделать более надежным для интернет-приложений.

Таким образом, html становится:

<html>
    <head>
        <script src="/js/jquery-1.3.2.min.js" type="text/javascript"> </script>

        <script type="text/javascript">
<!--
    var detailRequest = null;

    function StartDetailRequest() {
        detailRequest = jQuery.ajax({
            type: 'GET',
            url: '<%= Url.Action("EnquiryDetail", "Account", new { requestGuid = ViewData["detailRequestGuid"] }) %>',
            success: function (result) {
                if (result.length == 0) {
                    setTimeout("StartDetailRequest()", 500);
                }
                else {
                    $('#detail').html(result);
                    $("table tbody").each(function () { $("tr:odd", this).addClass("odd"); });
                }
            },
            error: function (xmlHttpRequest, textStatus, errorThrown) {
                $('#detail').html('Failed to load additional information:<br />' + textStatus + '<br />' + errorThrown);
            }
        });
    }

    $(function () {
        setTimeout("StartDetailRequest()", 500);
    });
//-->
        </script>
    </head>
    <body>
        <h2>Account Information</h2>
        <div>Some basic details here</div>
        <div><button onclick="location.assign(&quot;/somewhere-else&quot;)" type="button">Go somewhere else now</button></div>
        <div id="detail">
            <img src="/ajax-loading-animation.gif" alt="Loading ..." />
            Loading ...
        </div>
    </body>
</html>

На стороне сервера я делаю что-то вроде (ASP.NET MVC 2 с псевдокодом):

private Dictionary<Guid, DetailRequestObject> detailRequestList = new Dictionary<Guid, DetailRequestObject>();

[AcceptVerbs(HttpVerbs.Get)]
public ActionResult Index(string id)
{
  var model = GetTheBasicDetails(id);
  var request = CreateDetailRequestObject(id);

  CheckForTimedOutDetailRequests();

  detailRequestList.Add(request.Guid, request);

  ViewData["detailRequestGuid"] = request.Guid;

  return View(model);
}

[AcceptVerbs(HttpVerbs.Get)]
public ActionResult EnquiryDetail(Guid requestGuid)
{
  DetailRequestObject detailRequest = detailRequestList[requestGuid];

  if (detailRequest == null)
  {
    throw new TimeoutException("Timed out retrieving details");
  }
  else if (!detailRequest.IsComplete)
  {
    return Content("");
  }
  else
  {
    var details = detailRequest.Response();

    return PartialView(details);
  }
}

Класс DetailRequestObject инкапсулирует создание отдельного потока с использованием асинхронногомодель по вашему выбору, устанавливает флаг после завершения и собирает данные ответа.

У меня также есть метод CheckForTimedOutDetailRequests, который собирает запросы, для которых истек тайм-аут для извлечения, так что любые, которые были «прерваны», могут бытьпрояснилось.

Думаю, я бы предпочел, чтобы долго выполняющиеся запросы выполнялись в отдельной службе Windows, которая выполняла бы свою собственную очистку, регулирование запросов и тому подобное, но вышеприведенное работает так ...

0 голосов
/ 13 октября 2010

Вы пытались вызвать метод ajax после загрузки страницы

  <body onload="myFunctionThatCallsAjax()">

Есть некоторые различия в поведении браузера, когда вы встраиваете Javascript в код HTML. Использование onload гарантирует, что это не проблема.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...