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

Индикатор загрузки Chrome продолжает вращаться во время XMLHttpRequest

Я пишу веб-приложение AJAX, которое использует Comet/Long Polling, чтобы обновлять веб-страницу, и я заметил в Chrome, что он рассматривает страницу так, как будто она всегда загружается (значок для вкладки продолжает вращаться).

Я думал, что это нормально для Google Chrome + Ajax, потому что даже у Google Wave это поведение.

Хорошо сегодня я заметил, что Google Wave больше не держит значок загрузки, кто-нибудь знает, как они исправили это?

Здесь мой код вызова ajax

var xmlHttpReq = false;
// Mozilla/Safari
if (window.XMLHttpRequest) {
   xmlHttpReq = new XMLHttpRequest();
}
// IE
else if (window.ActiveXObject) {
   xmlHttpReq = new ActiveXObject("Microsoft.XMLHTTP");
}
xmlHttpReq.open('GET', myURL, true);
xmlHttpReq.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
xmlHttpReq.onreadystatechange = function() {
   if (xmlHttpReq.readyState == 4) {
      updatePage(xmlHttpReq.responseText);
   }
}
xmlHttpReq.send(null);
4b9b3361

Ответ 1

Я бесстыдно украл тестовый корпус Олега и немного поправил его, чтобы симулировать длительный опрос.

load.html:

<!DOCTYPE html>
<head>
  <title>Demonstration of the jQery.load problem</title>
  <script src="http://code.jquery.com/jquery-latest.js"></script>
  <script>
  jQuery(document).ready(function() {
    $('#main').load("test.php");
  });
  </script>
</head>
<body>
  <div id='main'></div>
</body>
</html>

test.php:

<?php
  sleep(5);
?>
<b>OK!</b>

Результат интересен: в Firefox и Opera индикатор загрузки не отображается во время XMLHTTPRequests. Chrome позволяет вращаться... Я подозреваю, что Google Wave больше не использует длительный опрос (но, например, опросы каждые X секунд, чтобы сохранить ресурсы), но я не могу его протестировать, так как у меня нет учетной записи.

EDIT: И я понял: после добавления небольшой задержки при загрузке test.php, которая может быть как можно меньше, индикатор загрузки останавливается после загрузки load.html:

jQuery(document).ready(function() {
  setTimeout(function () {
    $('#main').load("test.php");
  }, 0);
});

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

Ответ 2

Извините за мой общий ответ, но если вы хотите иметь независимую от браузера программу, вы должны использовать jQuery или другую вашу любимую библиотеку вместо низкоуровневого XMLHttpRequest и ActiveXObject ( "Microsoft.XMLHTTP" ).

Редакция: Я создаю два очень простых файла HTML: test.htm и load.htm и размещен там в одном каталоге на веб-сайте (попробуйте этот URL http://www.ok-soft-gmbh.com/jQuery/load/load.htm). Я не вижу эффекта, который вы описываете в своем вопросе. Сравните эти файлы с вашими примерами, и вы решите свою проблему.

load.htm:

<!DOCTYPE html PUBLIC
          "-//W3C//DTD XHTML 1.0 Strict//EN"
          "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head">
  <title>Demonstration of the jQery.load problem</title>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  <script src="http://code.jquery.com/jquery-latest.js"></script>
  <script type="text/javascript">
  jQuery(document).ready(function() {
    $('#main').load("test.htm");
  });
  </script>
</head>

<body>
  <div id='main'></div>
</body>
</html>

test.htm:

<b>OK!</b>

Ответ 3

Я не уверен в jQuery или Ajax, но у меня была аналогичная проблема с вставкой фрагментов в редактор Ace с помощью Менеджера фрагментов. При вставке кода в редактор справа, когда страница загружалась, страница, казалось бы, никогда не загружалась - значок вкладки будет вращаться навсегда. .setTimeout() работал очень непоследовательно. Он будет работать, когда страница загружается очень быстро, но не тогда, когда страница загружается медленнее. Это может быть из-за того, что я ничего не делал в $(document).ready() - я только вызывал свой код в конце тела документа.

Здесь решение no-jQuery, которое я нашел для моей проблемы с пиктограммой навсегда:

var tillPageLoaded = setInterval(function() {
    if( document.readyState === 'complete' ) {

        clearInterval(tillPageLoaded);
        // load whatever

    }    
}, 5);

В моем случае // load whatever был:

ace.config.loadModule('ace/ext/language_tools', function () {
    myEditorInstance.insertSnippet( 'some string' );
});

Ответ 4

используйте эту функцию

function getHTTPObject() {
 var xhr = false;
 if (window.XMLHttpRequest) {
  xhr = new XMLHttpRequest();
 } else if (window.ActiveXObject) {
  try {
   xhr = new ActiveXObject("Msxml2.XMLHTTP");
  } catch(e) {
   try {
    xhr = new ActiveXObject("Microsoft.XMLHTTP");
   } catch(e) {
    xhr = false;
   };
  };
 };
 return xhr;
};