Январь 27, 2005
Динамическая загрузка данных с помощью HTTPRequest
На первый взгляд, объект HttpRequest не представляет собой нечто особенное. Его возможности раскрываются полностью только тогда, когда вам необходимо сделать запрос GET или POST и обновить при этом только часть страницы. Такая необходимость возникает постоянно, и методы, используемые для достижения цели, далеко не самые оптимальные.
Традиционные пути решения проблемы обновления страницы — полная её перезагрузка. Варианты следующие:
- Заставить пользователя нажать F5
- Установить интервал обновления в теге META
- Обновлять страницу с помощью JavaScript через определённый интервал
- Подождать, пока пользователь не нажмёт кнопку, которая осуществляет нужный запрос
Недостаток всех перечисленных методов состоит в том, что обновление данных влечёт за собой полную перезагрузку страницы. И пользователь при этом обычно теряет текущую позицию просмотра на больших страницах. Кроме того, после перезагрузки теряются изменения, сделанные в других частях страницы (в других формах).
Предположим, что у нас есть страница, являющаяся порталом для управления сайтом. Одна её часть показывает журнал с действиями пользователей, другая – текущую загрузку, и третья отображает большие объёмы данных, которые приходится постоянно прокручивать. Если такая страница будет полностью перезагружаться, то с такой системой управления будет проблематично работать. Одну часть нужной информации мы можем просто пропустить, другую не заметить и т.п.
Одно из решений нашей задачи – фреймы. Работать, конечно, будет, но фреймы решают проблему только визуальной зависимости. Также, иногда мы просто не можем разбить всю систему интерфейса на кучку мелких страничек.
А как же апплеты? Да, апплеты способны эффективно справиться с такой задачей. Но эта технология сейчас не в почёте, и требует установленной виртуальной машины Java ( JVM). Заставлять пользователей её устанавливать или включать не представляется разумным. Другая проблема состоит в том, что апплеты могут общаться только с тем сервером, с которого они были загружены. Сделано это с целью безопасности, однако может существенно ограничить ваши потребности.
На помощь приходит объект HttpRequest
Основная задача объекта HttpRequest – отправлять GET или POST запросы. Давайте взглянем на его свойства и методы:
Свойство | Значение |
readyState | Состояние документа |
status | Код ответа HTTP |
responseText | Результат в виде строки |
responseXML | Результат в виде XML |
Метод | Значение |
open( method, URL, async, user, password ) | Создаёт соединение с указанным URL |
send( data ) | Выполняет запрос |
Начнём с методов и их параметров:
- Для метода open() :
-
- Параметр method - метод HTTP ( GET или POST ).
- URL – адрес
- Параметр async определяет , будет ли запрос асинхронным или нет . Если запрос будет не асинхронным , то вся страница будет заблокирована , пока запрос не завершится . Очевидно , этот параметр должен быть true .
- user и password позволяют ввести параметры авторизации .
- Метод send() осуществляет запрос .
-
- Если совершается запрос GET, параметр data может быть null . Чтобы отправить данные на сервер при помощи запроса POST, параметр data будет содержать наши данные.
Свойства:
- readyState – представляет состояние документа по адресу URL . Его можно использовать для того, чтобы узнать, загрузилась ли страница.
- status – содержит код ответа HTTP (например, 200), после того, как запрос завершился.
- Свойства responseText и responseXML содержат результирующий документ в виде текста или же в виде XML.
Давайте рассмотрим простой пример использования HttpRequest. Код файла test-request.html:
<html>
<script>
var xmlDoc = null ;
function load() {
if (typeof window.ActiveXObject != 'undefined' ) {
xmlDoc = new ActiveXObject("Microsoft.XMLHTTP");
xmlDoc.onreadystatechange = process ;
}
else {
xmlDoc = new XMLHttpRequest();
xmlDoc.onload = process ;
}
xmlDoc.open( "GET", "test-request.html", true );
xmlDoc.send( null );
}
function process() {
if ( xmlDoc.readyState != 4 ) return ;
document.getElementById("output").value = xmlDoc.responseText ;
}
function empty() {
document.getElementById("output").value = '' ;
}
</script>
<body>
<textarea id="output" cols="60" rows="20"><empty></textarea>
<br></br>
<button onclick="load()">Load</button>
<button onclick="empty()">Clear</button>
</body>
</html>
Скопируйте данный код и создайте новый HTML-файл. После загрузки этого файла мы увидим пустой элемент textarea с двумя кнопками Load и Clear. После нажатия на кнопку Load отрабатывает функция load(), которая и загружает с помощью HttpRequest файл test-request.html (т.е. тот же самый файл, в данном случае) в область textarea . Функция empty() просто очищает область textarea в первоначальное состояние.
Посмотрим на функцию load():
function load() {
if (typeof window.ActiveXObject != 'undefined' ) {
xmlDoc = new ActiveXObject("Microsoft.XMLHTTP");
xmlDoc.onreadystatechange = process ;
}
else {
xmlDoc = new XMLHttpRequest();
xmlDoc.onload = process ;
}
xmlDoc.open( "GET", "test-request.html", true );
xmlDoc.send( null );
}
В этой функции мы создаём новый объект HttpRequest. Заметьте, как мы проверяем браузер: если условие if верно (ActiveXObject есть), значит браузер – MSIE, и нужно создавать версию ActiveX объекта HttpRequest. Если нет, то используется встроенный объект XMLHttpRequest браузера Mozilla. В любом случае после создания объекта ему нужно «приказать» вызвать метод process(), после того, как браузер закончит загрузку страницы. Затем мы вызываем метод open() с необходимыми параметрами (тип запроса – GET, адрес страницы, и асинхронный метод запроса). Запрос отправляется методом send(). Надо отметить, что приведённый код работает в браузерах Internet Explorer 6.0 и Mozilla Firefox 1.0.
После того, как запрос страницы завершён, браузер автоматически вызывает метод process(), который обновляет содержимое textarea. Важно отметить первую строку:
if ( xmlDoc.readyState != 4 ) return ;
Этим мы проверяем , обработан ли запрос полностью . И если нет, то нужно просто выйти из функции. Вторая строка просто устанавливает возвращённый результат responseText в textarea.
Заключение
Хотелось бы отметить, что с помощью этого метода можно делать довольно сложные динамические веб-приложения, такие, как почтовая система Gmail, сервис Google Suggest и т.п. Пользователи получают обновления страницы без полной перезагрузки, которая многих просто раздражает.
Единственный недостаток данного механизма по сравнению с апплетами состоит в том, что запрос данных происходит со стороны клиента. Сервер не может уведомить клиента о том, что появились новые данные, которые уже можно загрузить. Соответственно, постоянные запросы могут создать серьёзный трафик.
Автор: Дуг Дэвис
Перевод и коррекция: Сергей Яценко
Комментарии
- 1. 27.01.05 14:40 От: iogan18tm
-
http://jibbering.com/2002/4/httprequest.html
здесь тоже кое-что написано. В частности в плане кросс-браузерности этого дела. Ну и комментарии по ходу - 2. 07.02.05 23:46 От: Илья
-
Не совсем согласен с фразой автора "Другая проблема состоит в том, что апплеты могут общаться только с тем сервером, с которого они были загружены."
Апплеты можно подписывать (цифровая подпись), тогда появляется возможность обращаться к другим серверам и еще куча возможностей. - 3. 20.02.05 23:19 От: Умберто
-
"JSHttpRequest: динамическая подкачка данных без перезагрузки страницы"
http://dklab.ru/chicken/nablas/41.html
IMHO, там отличное решение (и от других, тоже :) - 4. 02.03.05 18:34 От: Петр
-
Хорошая статья.
dklab тоже молодцы. - 5. 04.05.05 17:35 От: intro
-
То что искал, спасибо
- 6. 16.08.05 12:36 От: ip
-
отличная статья.Понятно, а главное на русском!!!
- 7. 21.12.05 14:17 От: Yurik
-
а как на шчот Опери
- 8. 25.01.06 16:25 От: green
-
Что касается использования технологии
Года 2 назад писал подобную вещь и натолкнулся на ограничение QUERY_STRING по длине - так что "прыгать и хлопать в ладоши" от универсальности метода я не советую
- 9. 29.01.06 22:44 От: aleksey.stepanov
-
так отправляй POSTом данные
- 10. 12.02.06 21:46 От: BF
-
Люди как POSt'oм отпрамвлять данные просто переменную в SEND'e не укажешь, он её не отправляет, помогите?!?!?!
- 11. 13.02.06 04:19 От: Big_Foot
-
Вот решил тут аякса изучить, но пока ума маловато,Люди научите отравлять не гетом а постом, пробовал тут xmlDoc.send( null ) указывать переменную вместо нул, ничего на пхп скрирт который генерит страницу не приходит, или скорее не отправляется, ещё читал где-то что проблемф с русским но до этого думаю рано ещё :-))). Если кто нить может покажите примерчик или ссылочку. ПЛЗ
- 12. 27.02.06 20:02 От: Nexus
-
Для того, чтобы передать данные POST-ом, необходимо encode-ить данные. Например, вот так.
request.send(urlEncodeData(data));
function urlEncodeData(data) {
var query = [];
if (data instanceof Object) {
for (var k in data) {
query.push(encodeURIComponent(k) + "=" + encodeURIComponent(data[k]));
}
return query.join('&');
} else {
return encodeURIComponent(data);
}
} - 13. 27.02.06 20:04 От: Nexus
-
data в нашем случае может быть либо обычной переменной, либо ассоциативным массивом
- 14. 03.09.06 21:24 От: uks
-
По-моему, про get'ы и post'ы лучше всего читать тут:
http://www.intuit.ru/department/internet/cgi/ - 15. 20.09.06 14:41 От: pchelovod
-
Цитата: "Чтобы отправить данные на сервер при помощи запроса POST, параметр data будет содержать наши данные."
Вопрос: В каком формате должны быть передаваемые в скрипт методом POST данные?!
Пытался делать так:
var MyVar="777";
xmlDoc.send(MyVar);Пытался и так как советовал Nexus. Результат один - вызываемый php-скрипт не видит никаких переменных :(
- 16. 25.09.06 17:18 От: pchelovod
-
Отвечаю сам же на свой вопрос :)
"The parameter to the send() method can be any data you want to send to the server if POST-ing the request. The data should be in the form of a query string, like:name=value&anothername=othervalue&so=on
Note that if you want to POST data, you have to change the MIME type of the request using the following line:
http_request.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
Otherwise, the server will discard the POSTed data. "Читать тут: http://developer.mozilla.org/en/docs/AJAX:Getting_Started
- 17. 30.05.07 13:45 От: Vanot
-
Спасибо!
- 18. 20.01.09 21:12 От: Валерий Темный
-
Афтару огромейнейший респект и спасибище!!!! Благодаря вашей статье я реализовал необъятные возможности на своем портале и в 100-ни раз уменьшил нагрузку на сервер!!!
- 19. 01.02.11 12:20 От: )!(ek@
-
Офигенно=))
Пасибо...начал врубаться=) - 20. 01.11.11 09:06 От: mic
-
Grazie!
а как xmlDoc.responseText вывести в , чтоб браузер теги обработал?