2009-07-10 4 views
14

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

Это похоже на HTTP Streaming (current) шаблон с сайта Ajaxpatterns.

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

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

Вы должны обязательно добавить этот пример кода в качестве ответа и пометить его как правильный! –

+4

«если пользователь не хочет устанавливать jQuery»? – Basic

+0

Привет, только что наткнулся на ваше решение, но я боюсь, что он по-прежнему не будет работать с IE, поскольку, когда вы попытаетесь получить ответText, пока запросы еще не закончились, вы получите следующее message: «Данные, необходимые для завершения этой операции, пока недоступны». –

ответ

2

Решение, с которым вы связались, на самом деле не является 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> 
+0

Не то, что я хочу. Расчет на сервере генерирует вывод в текстовом формате. С XHR я могу получить этот ответ непосредственно в клиенте (onreadystatechange на флеше/таймер) и отредактировать веб-страницу в соответствии с частичными данными, которые я получаю. –

+0

Что вы не хотите? Долгий опрос? Я не рекомендую ни один из методов - я просто говорю вам, каковы ваши варианты. –

+0

Если вы хотите использовать длинный пул (комета), вам следует использовать программное обеспечение сервера Meteor, потому что Apache не предназначен для такого рода вещей. И есть также библиотека javascript, которая обрабатывает почти все для вас, я просто не могу вспомнить ее имя, опубликует ее позже. – usoban

0

Я хотел бы взглянуть на вращался

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

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

и искать «Orbited.CometTransports»

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