Кросс-браузерная реализация шаблона AJAX "HTTP Streaming" (push)

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

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

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

Проблема начинается с генерации XMLHttpRequest в кросс-браузере, но я считаю, что основным элементом является то, что не все браузеры правильно реализуют onreadystatechange из XMLHttpRequest; не все браузеры вызывают событие onreadystatechange на каждом сервере flush (BTW). Как заставить сервер сбрасываться из CGI script (в 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;
}

Ответы

Ответ 1

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

В примере, на который они ссылаются, вы можете легко увидеть себя с помощью firebug. Включите панель Net - нет записей 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>

Ответ 2

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

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

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

и найдите "Orbited.CometTransports"

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