Остановите браузер «Throbber of Doom» при загрузке кометы / сервера нажмите XMLHttpRequest - PullRequest
7 голосов
/ 14 ноября 2009

(Этот вопрос похож на этот , но он предназначен для использования XMLHttpRequest вместо iframe для Comet.)

Я запускаю длинный асинхронный опрос, подобный этому:

var xhr = new XMLHttpRequest();
xhr.open('POST', url);
xhr.send();

Если я сделаю это внутри <script>...</script> в заголовке, документ будет загружаться вечно. (Я тестирую это в Safari на Mac OS X и iPhone, и это единственный браузер, который мне нужно поддерживать).

Использование событий DOMContentLoaded или load не будет работать.

Будет работать setTimeout с достаточно большой задержкой . 0 не будет, 1000 будет, 100 будет несколько раз, а не в другой раз. Мне это неудобно.

Единственный способ, с помощью которого я нашел, - это сочетание обоих:

document.addEventListener('DOMContentLoaded', function () {
    setTimeout(function () {
        var xhr = new XMLHttpRequest();
        xhr.open('POST', url);
        xhr.send();
    }, 0);
});

Я думаю, что это решает проблему на данный момент, но я все еще боюсь, что это сломается в будущем. // Редактировать: это также не работает надежно.

Кто-нибудь знает более надежный способ?

Ответы [ 4 ]

2 голосов
/ 24 ноября 2009

Я не уверен, но кажется, что если браузер показывает, что он все еще загружает, то это совершенно правильно - разве это не то, чем в основном является программирование на Comet? Сервер все еще отправляет небуферизованный контент, и когда он передается в блоке javascript, он выполняется, что позволяет серверу отправлять события в браузер клиента.

В первые дни Ajax (например, в IE6, где XMLHttpRequest был отдельным объектом ActiveX), я ожидал, что браузер не будет знать, что он все еще ждет.

Но в Safari 4, Chrome, FX3.5 и во всех современных браузерах встроен XMLHttpRequest - он знает, что он все еще ждет, пока сервер покажет поток своего контента, точно так же, как и при <IFrame>

Короче говоря - я ожидал бы, что любой подход Comet покажет, что браузер все еще загружает, потому что это так. Я ожидаю, что любой обходной путь, который вы найдете, будет исправлен в будущих сборках, потому что Comet по сути является хаком, чтобы заставить работать серверную модель.

Однако они начали встраивать реальную поддержку серверного push-кода в HTML 5.

Поддерживает ли мобильный Webkit тег HTML 5 draft event-source? Если это так, вы можете попробовать это.

Тогда у вас будет что-то вроде этого:

<!-- new HTML 5 tag supporting server-push -->
<event-source src="http://myPushService.com" id="service">

<script type="text/javascript">

    function handleServiceEvent(event) {
        // do stuff
    }

    // tell browser to fire handleServiceEvent in response to server-push
    document.getElementById('service').addEventListener('event name', handleServiceEvent, false);
</script>
1 голос
/ 18 ноября 2009

Когда вы говорите:

... это приведет к тому, что документ будет загружаться вечно.

Что именно вы подразумеваете под этим? Вы имеете в виду, что индикатор выполнения никогда не заканчивается? Или фактический документ даже не полностью виден? Маловероятно, что запрос AJAX остановит загрузку всего документа, но в любом случае ...

Случай 1: индикатор выполнения никогда не заканчивается

Скорее всего, это вызвано тем, что запрос AJAX никогда не выполняется. Вы пытались посмотреть на запрос AJAX в консоли Firebug? Он покажет вам как сделанный запрос, так и ответ сервера. Я бы начал здесь только для того, чтобы убедиться, что сервер отправляет что-то назад.

Случай 2: элементы документа не полностью загружены / видимы

Вы можете попробовать поместить тег прямо перед тегом .

Когда вы делаете это, дерево DOM полностью загружается до того, как сценарий даже выполняется, вам не нужно ждать запуска domready или onload. Также имейте в виду, что загружаемое дерево DOM не означает, что содержимое DOM (например, изображения) полностью загружено (вам нужно подождать, пока «onload» будет уверен что)

В любом случае, я бы попытался поместить скрипт прямо перед тегом , чтобы у скелета DOM был шанс построить.

Примечание:

Вы просматриваете свою страницу с помощью какого-либо отладчика? Firebug, Webkit Inspector. В частности, Webkit Inspector фактически остановит обработку всего документа, если у вас открыта консоль и обнаружена ошибка JavaScript. Вы видите какие-либо ошибки JavaScript в консоли? Загружается ли страница, если вы выключаете отладчики?

0 голосов
/ 25 ноября 2009

Похоже, что в некоторых браузерах метод open (...) отправляет ajax-запрос синхронно по умолчанию, если не указан третий параметр? Попробуйте:

xhr.open('POST', url, true);

, чтобы явно сделать вызов асинхронным.

0 голосов
/ 21 ноября 2009

Не могли бы вы попытаться использовать событие загрузки вместо события DOMContentLoaded. Это должно иметь значение, так как он вызывается только тогда, когда страница полностью загружена.

var xhr;
document.addEventListener('load', function () {
    xhr = new XMLHttpRequest();
    xhr.open('POST', url);
    xhr.send();
});

Это должно работать. Тем не менее, я не часто работаю с Comet, поэтому у меня нет возможности проверить это в данный момент.

РЕДАКТИРОВАТЬ: Извините, только что увидел, что Мэтт уже сказал это.

...