Rambler's Top100
 
 
  05 декабря 2008 года Компьюлента
CIO
Терралаб
Бизнес-журнал
в поле зрения | обзоры и тесты | своя игра | интерактив
Как написать AJAX-приложение
Автор: Виталий Акулов
Опубликовано 18 апреля 2006 года

Это два года назад AJAX был в диковинку (да и самого слова AJAX тогда ещё не выдумали). Теперь веб-приложения, страницы которых обновляются "на лету", в порядке вещей. Даже наоборот, без AJAX трудно и представить себе некоторые сервисы.

Как работали обычные веб-приложения? Как правило, на событие (клик по ссылке или нажатие на кнопку) браузер реагировал отправкой запроса серверу. Когда с сервера приходил ответ, всё содержимое страницы полностью обновлялось.

Одна из проблем состояла в том, что при обновлении содержимого страницы веб-приложение переходит в новое состояние. Из информации о предыдущем состоянии сохраняются только данные, переданные в запросе. Чем более точная информация о прежнем состоянии системы требуется, тем больше данных необходимо пересылать в запросе.

Другим недостатком является необходимость пересылать повторяющиеся массивы данных клиенту после каждого события. Например, если пользователь ошибся при заполнении формы, то вместо короткого сообщения об ошибке приходится снова загружать и форму, и всю введённую ранее информации.

Современные браузеры, поддерживающие стандарты W3C DOM, позволяют вывести веб-приложение на новый уровень.

Схема взаимодействия остается почти такой же. Вот только отправляет запрос и получает ответ с сервера теперь скрипт на стороне клиента, а вместо обновления всей страницы - обновляется только ее часть (вместо обновления могут предприниматься иные действия, например, отправляться следующий запрос).

Веб-приложение получается распределенным, и часть логики находится на стороне клиента, а часть - на стороне сервера. Такие приложения и называют термином "AJAX Applications" (аббревиатура расшифровывается как Asynchronous Javascript And Xml Applications).

Подробнее про AJAX можно прочитать здесь

Объект XMLHTTPRequest

Для асинхронных запросов от клиента к серверу на стороне браузера служит специальный объект под названием XMLHTTPRequest.

Перечислим методы и свойства объекта, которые будут использованы далее:

  • XMLHTTPRequest.open("method", "URL", async, "uname", "pswd") – создает запрос к серверу.
    • method – тип запроса, например, GET
    • URL – URL запроса, например http://localhost/file.xml
    • async – если True, то будет использоваться асинхронный запрос, то есть выполнение скрипта продолжится после отправки запроса. В противном случае скрипт будет ожидать ответа от сервера, заморозив UI.
  • uname, pswd – логин и пароль для простой веб-авторизации.
  • XMLHTTPRequest.send("content") – отправляет запрос на сервер. Значением content могут быть данные для POST-запроса или пустая строка.
  • XMLHTTPRequest.onreadystatechange – обработчик событий срабатывающий на каждое изменение состояния объекта. Состояния объекта могут быть следующими:
    • 0 - до того как запрос отправлен (uninitialized)
    • 1 - объект инициализирован (loading)
    • 2 - получен ответ от сервера (loaded)
    • 3 - соединение с сервером активно (interactive)
    • 4 - объект завершил работу (complete)
  • XMLHTTPRequest.responseText – возвращает полученные от сервера данные в виде строки.
  • XMLHTTPRequest.responseXML – если ответ сервера пришел в виде правильного XML, возвращает XML DOM объект.
  • XMLHTTPRequest.status – возвращает статус HTTP-ответа в виде числа. Например, 404 если запрашиваемая страница не была найдена на сервере.

Рассмотрим применение объекта на примере простого AJAX-приложения.

Поле SELECT с поиском

Предположим у нас есть таблица, в которой порядка миллиона записей. Пользователю необходимо выбрать всего одну запись из таблицы (реализация отношения "один ко многим"). Выбор пользователя является всего лишь одним из этапов заполнения большой веб-формы.

Естественно, для того, чтобы пользователь мог выбрать нужную запись из миллиона, нужны какие-то средства поиска этой самой записи. Например, простой текстовый поиск по наименованию.

В традиционном веб-приложении для этой цели пришлось бы использовать отдельную страницу и сохранять остальные данные формы в сессии пользователя, либо разбивать процесс заполнения формы на несколько этапов. В AJAX-приложении дополнительная страница не нужна.

Выбор записи будет реализован с помощью двух элементов веб-формы. Первый элемент - это текстовое поле, где пользователь вводит ключевое слово. Оно отсылается на сервер, а тот возвращает только те строки из таблицы, которые удовлетворяют условию поиска. Ответ сервера (в виде списка) помещается в поле SELECT, в котором пользователь и сделает окончательный выбор. Таким образом, при отправке всей формы на сервер попадет выбранное в поле SELECT значение в виде ID записи из большой таблицы.

В HTML выглядеть это может так:

<input type="text"
   onkeyup="lookup(this.value, 'id_select', 
   'http://localhost/cgi-bin/xmlhttp.cgi')" />	
<select id="id_select" name="id_select">
<option selected="selected" value=""></option>
</select>

На любое событие KeyUp (отжатие кнопки) в текстовом поле вызывается функция lookup ('текст', 'id-selecta', 'url')

function lookup(text, select_id, url) {
        // Получаем объект XMLHTTPRequest
        if(!this.http){
            this.http = get_http();
            this.working = false;
        }
        // Запрос
        if (!this.working && this.http) {
            var http = this.http;
            // Если в текстовом поле менее трёх
            // символов – не делаем ничего
            if (text.length <3 ) return;
		//добавляем закодированный текст
                //в URL запроса
            url = url + "?text="+encodeURIComponent(text);
      //создаём запрос
            this.http.open("GET", url, true);
            //прикрепляем к запросу функцию-обработчик
            //событий
            this.http.onreadystatechange = function() {
	// 4 – данные готовы для обработки
                if (http.readyState == 4) {
                    fill(select_id, http.responseText);
                    this.working = false;
                  }else{
                     // данные в процессе получения, 
                     // можно повеселить пользователя
                     //сообщениями 
                     // ЖДИТЕ ОТВЕТА
                  }
            }
            this.working = true;
            this.http.send(null);
        }
        if(!this.http){
              alert('Ошибка при создании XMLHTTP объекта!')
        }
    }

Как видно, в начале мы получаем XMLHTTP-объект с помощью функции get_http(). Затем поисковый текст кодируется в стиле URL и формируется GET-запрос к серверу. URL запроса в данном случае будет выглядеть приблизительно так: http://localhost/cgi-bin/xmlhttp.cgi?text=...

Скрипт на сервере, получив значение text, делает поиск в таблице и отсылает результат клиенту. В обработчике событий объекта XMLHTTP, когда данные от сервера получены и готовы к использованию, вызывается функция fill('select_id', 'data'), которая заполнит список SELECT полученными данными.

Функция get_http() – это кросс-браузерная реализация получения объекта XMLHTTP (в каждом браузере он получается по-своему). Её реализацию с комментариями вы можете легко найти в интернете, это, так сказать, пример из учебника.

function get_http(){
    var xmlhttp;
    /*@cc_on
    @if (@_jscript_version >= 5)
        try {
            xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");
        } catch (e) {
            try {
                xmlhttp = new 
                ActiveXObject("Microsoft.XMLHTTP");
            } catch (E) {
                xmlhttp = false;
            }
        }
    @else
        xmlhttp = false;
    @end @*/
    if (!xmlhttp && typeof XMLHttpRequest != 'undefined') {
        try {
            xmlhttp = new XMLHttpRequest();
        } catch (e) {
            xmlhttp = false;
        }
    }
    return xmlhttp;
}

Функция fill() получает на вход значение параметра ID списка SELECT, который необходимо заполнить, и сами данные, полученные с сервера.

Для простоты предположим, что данные с сервера мы получаем в виде таблицы, поля которой разделены символом табуляции '\t', а строки - символом переноса строки '\n':

id1	\t	name1	\n
id2	\t	name2	\n
...

На основании содержимого этой таблицы мы будем заполнять поле SELECT элементами OPTION.

function fill (select_id, data){
    // поле SELECT в переменную в виде объекта	
    var select = document.getElementById(select_id);
    // очищаем SELECT
    select.options.length = 0;
    // если данных нет – не делаем больше ничего
    if(data.length == 0) return;
    // в массиве arr – строки полученной таблицы
    var arr = data.split('\n');
    // для каждой строки
    for(var i in arr){
        // в массиве val – поля полученной таблицы
        val = arr[i].split('\t');
        // добавляем новый объект OPTION к нашему SELECT
        select.options[select.options.length]=
        new Option(val[1], val[0], false, false);
    }
}

Готово. Теперь для любой веб-формы приложения мы можем реализовать подобный выбор значения из многомиллионного списка, который для пользователя будет выглядеть как считанные нажатия клавиш. В локальной сети выбор происходит практически мгновенно. В случае нестабильного или низкоскоростного соединения с сервером, необходимо также оповещать пользователя о том, что загрузка данных с сервера еще не завершена. Полезно предусмотреть и средства для реакции на обрыв соединения.

ПОСЛЕДНИЕ КОММЕНТАРИИ
 
ТАКЖЕ В РАЗДЕЛЕ
29 июля 2008 года
Карманный Youtube 
 
САМОЕ ПОПУЛЯРНОЕ
Большой обман на маленьких носителях
Подобно сотовым телефонам, флэшка из элитарного продукта в конце концов стала массовым. Но только ли стремительным научно-техническим прогрессом объясняется дешевизна современных флэшек?
Как дела, "хромой"?
Два месяца назад Google с помпой объявила о выходе в свет бета-версии собственного браузера - Chrome, основанного на движке WebKit. Теперь, когда пыль улеглась, давайте посмотрим, как дела у гугловского подопечного.
8,9-дюймовый месяц
Проверим на практике: может ли нетбук полностью заменить обычный портативный компьютер? А рабочую или домашнюю машину? Не исключено, что некоторые читатели будут удивлены выводами этого месячного эксперимента.
Самый быстрый на планете
Пока продажи процессоров Core i7 только начинаются, мы подводим итоги знакомства, ибо работаем на новой платформе без малого месяц. Действительно, ничего быстрее Intel еще не делала. Но как почувствовать эту скорость?
/  бумажный номер

Тема номера: Кризис в ИТ Читайте на сайте тему номера "Кризис в ИТ" и другие статьи из журнала "Компьютерра" от 04 ноября 2008 года
  Архив номеров журнала

О проекте | Реклама на сайте | Рассылки сайта | КПК–версия | RSS-трансляция

© ООО «Компьютерра–Онлайн», 1997 — 2008.
При цитировании и использовании любых материалов ссылка на портал «Компьютерра–Онлайн» обязательна (для Интернет–изданий — www.computerra.ru)
Редакция сайта: site@computerra.ru
Техподдержка сайта: websupport@computerra.ru
Редакция журнала: inform@computerra.ru
Отдел рекламы: reklama@computerra.ru
Телефон: (495) 232–22–61, (495) 232–22–63
Работает на «Битрикс: Управление сайтом»
Почта защищена сервером «СПАМОРЕЗ»
Трилан — продвижение сайта,
поисковая оптимизация сайта

Сайт работает на сервере DEPO Computers
Rambler's Top100