Клиентская веб-страница запроса с сервера. Затем Клент просит сделать дополнительные расчеты; Сервер выполняет серию вычислений и отправляет частичные результаты, как только они становятся доступны (текстовый формат, каждая строка содержит отдельный полный элемент). Клиент обновляет веб-страницу (с 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;
}