Кросс-браузерная реализация шаблона AJAX «HTTP Streaming» (push) - PullRequest
14 голосов
/ 11 июля 2009

Клиентская веб-страница запроса с сервера. Затем Клент просит сделать дополнительные расчеты; Сервер выполняет серию вычислений и отправляет частичные результаты, как только они становятся доступны (текстовый формат, каждая строка содержит отдельный полный элемент). Клиент обновляет веб-страницу (с JavaScript и DOM), используя информацию, предоставленную сервером.

Это похоже на шаблон HTTP Streaming ( текущая версия) с сайта Ajaxpatterns.

Вопрос в том, как сделать это кросс-браузерным (не зависящим от браузера) способом, предпочтительно без использования JavaScript-фреймворков или с использованием какой-либо облегченной фреймворк, такой как jQuery.

Проблема начинается с генерации XMLHttpRequest в кросс-браузерной манере, но я думаю, что основной вопрос заключается в том, что не все браузеры правильно реализуют onreadystatechange из XMLHttpRequest ; не все браузеры вызывают событие onreadystatechange на каждом сервере сброса (кстати, как заставить сервер сбрасывать из сценария CGI (в Perl)?). Пример кода на Ajaxpatterns решает эту проблему с помощью таймера; я должен отбросить решение таймера, если я обнаружу частичный ответ от onreadystatechange?


Добавлено 11.08.2009

Текущее решение:
Я использую следующую функцию для создания объекта XMLHttpRequest:

function createRequestObject() {
        var ro;
        if (window.XMLHttpRequest) {
                ro = new XMLHttpRequest();
        } else {
                ro = new ActiveXObject("Microsoft.XMLHTTP");
        }
        if (!ro)
                debug("Couldn't start XMLHttpRequest object");
        return ro;
}

Если бы я использовал какую-то (желательно облегченную) среду JavaScript, такую ​​как jQuery, я бы хотел иметь запасной вариант, если пользователь решит не устанавливать jQuery.

Я использую следующий код для запуска AJAX; setInterval используется потому, что некоторые браузеры вызывают onreadystatechange только после того, как сервер закрывает соединение (что может занять до десятков секунд), а не как только сервер сбрасывает данные (примерно каждую секунду или чаще).

function startProcess(dataUrl) {
        http = createRequestObject();
        http.open('get', dataUrl);
        http.onreadystatechange = handleResponse;
        http.send(null);

        pollTimer = setInterval(handleResponse, 1000);
}

Функция handleResponse является наиболее сложной, но ее эскиз выглядит следующим образом. Можно ли сделать это лучше? Как это можно сделать с помощью какой-нибудь облегченной среды JavaScript (например, jQuery)?

function handleResponse() {
    if (http.readyState != 4 && http.readyState != 3)
        return;
    if (http.readyState == 3 && http.status != 200)
        return;
    if (http.readyState == 4 && http.status != 200) {
        clearInterval(pollTimer);
        inProgress = false;
    }
    // In konqueror http.responseText is sometimes null here...
    if (http.responseText === null)
        return;

    while (prevDataLength != http.responseText.length) {
        if (http.readyState == 4  && prevDataLength == http.responseText.length)
            break;
        prevDataLength = http.responseText.length;
        var response = http.responseText.substring(nextLine);
        var lines = response.split('\n');
        nextLine = nextLine + response.lastIndexOf('\n') + 1;
        if (response[response.length-1] != '\n')
            lines.pop();

        for (var i = 0; i < lines.length; i++) {
            // ...
        }
    }

    if (http.readyState == 4 && prevDataLength == http.responseText.length)
        clearInterval(pollTimer);

    inProgress = false;
}

Ответы [ 2 ]

2 голосов
/ 11 июля 2009

Решение, на которое вы ссылаетесь, на самом деле вовсе не AJAX. Они называют это HTTP Streaming, но по сути это просто длинный опрос.

В примере, на который они ссылаются, вы можете легко увидеть это с помощью firebug. Включите панель «Сеть» - XHR-записи отсутствуют, но загрузка исходной страницы занимает всего 10 секунд. Это потому, что они используют PHP за кулисами, чтобы задержать вывод HTML. В этом суть длинного опроса: HTTP-соединение остается открытым, а периодический HTML-код отправляется с помощью команд javascript.

Вы можете сделать опрос полностью на стороне клиента, однако, с помощью setTimeout () или setInterval ()

Пример jQuery

<script type="text/javascript">
  $(document).ready(function()
  {
    var ajaxInterval = setInterval( function()
    {
      $.getJSON(
        'some/servie/url.ext'
        , { sample: "data" }
        , function( response )
          {
            $('#output').append( response.whatever );          
          }
      );
    }, 10000 );  
  });
</script>
0 голосов
/ 15 июля 2009

Я бы посмотрел на орбиту

Они используют несколько реализаций кометного транспорта, которые они выбирают в зависимости от конфигурации и перехвата браузера.

См. http://orbited.org/svn/orbited/trunk/daemon/orbited/static/Orbited.js

и ищите "Orbited.CometTransports"

Некоторые из разных транспортов должны быть согласованы с серверной реализацией, поэтому посмотрите на стороне сервера и для орбиты.

...