Кросс-браузерная реализация шаблона 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"
Некоторые из разных транспортов должны соответствовать реализации бэкэнд, поэтому также смотрите на серверную сторону для орбитальных устройств.