Клиентский запрос веб-страницы с сервера. Затем Клент просит провести дополнительные вычисления; сервер выполняет серию вычислений и отправляет частичные результаты, как только они становятся доступными (текстовый формат, каждая строка содержит отдельный полный элемент). Клиент обновляет веб-страницу (с помощью JavaScript и DOM), используя информацию, предоставленную сервером.
Кажется, это соответствует HTTP Streaming (current version) с сайта Ajaxpatterns.
Вопрос в том, как сделать это кроссбраузерным (независимо от браузера) способом, желательно без использования фреймворков JavaScript или с использованием некоторого легкого фреймворка, такого как jQuery.
Проблема начинается с генерации XMLHttpRequest в кроссбраузерном режиме, но я думаю, что основной момент заключается в том, что не все браузеры правильно реализуют onreadystatechange
from XMLHttpRequest; не все браузеры вызывают событие onreadystatechange
на каждом сбросе сервера (кстати, как заставить сбросить сервер из сценария CGI (в Perl)?). Пример кода на Ajaxpatterns решает эту проблему с помощью таймера; мне следует отказаться от таймера, если я обнаружил частичный ответ от onreadystatechange
?
Добавлено 08.11.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;
}