Индикатор загрузки 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);
Ответы
Ответ 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;
};