Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

Как написать AJAX-приложение

Автор: Виталий Акулов
источник: Компьютерра

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

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

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

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

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

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

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

Объект 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);
    }
}

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

Оставить комментарий

Комментарий:
можно использовать BB-коды
Максимальная длина комментария - 4000 символов.
 

Комментарии

1.
29K
05 мая 2007 года
elisey
0 / / 05.05.2007
+1 / -0
Мне нравитсяМне не нравится
5 мая 2007, 12:49:03
[post]Системная ошибка № -10728996748- ЭТО СВЯЗАНО С кодировкой? я исправил это посылкой заголовка с window-1251[/post]

У меня почему-то всё равно выходит эта ошибка, не знаю, как её исправить. Посылаю заголовок header("Content-Type: text/plain; charset=window-1251") - толку нет, опять та же ошибка (браузер - IE 6). Может, ещё какой-то заголовок нужен, не подскажет кто?

2.
26K
03 февраля 2007 года
Zabini
0 / / 03.02.2007
Мне нравитсяМне не нравится
3 февраля 2007, 15:27:30
Системная ошибка № -10728996748- ЭТО СВЯЗАНО С кодировкой? я исправил это посылкой заголовка с window-1251
3.
24K
02 декабря 2006 года
sj1987
0 / / 02.12.2006
Мне нравитсяМне не нравится
2 декабря 2006, 14:57:30
Кто то писал библиотеки для svg
Загрузка слоёв, и т.д.
Буду рад любой помощи
4.
23K
02 ноября 2006 года
dXdYdZ
0 / / 02.11.2006
Мне нравитсяМне не нравится
2 ноября 2006, 02:38:51
JSON

Написал библиотеку для автоматической генерации DOM (HTML) по шаблону. Теперь для использования JSON мне достаточно просто вызвать функцию build(json,tag,str), где json-полученный с помощью eval объект, tag-узел DOM для генерации содержимого, srt-шаблон. Теперь работаю с JSON просто и быстро.

p. s. Принимаю предложения о сотрудничестве(dojo-one@yandex.ru)
5.
20K
04 августа 2006 года
dnace
0 / / 04.08.2006
Мне нравитсяМне не нравится
4 августа 2006, 17:18:54
проблема решена, настройками апача
6.
20K
04 августа 2006 года
dnace
0 / / 04.08.2006
Мне нравитсяМне не нравится
4 августа 2006, 14:44:05
надоело бороться и с субсисом тоже, через чур громоздкий класс, к тому же глючный. Кодирует скрипты нормально, русский тоже. Вот я пытался им передавать javascript, но по умолчанию он не запускается. Зачем он тогда нужен? Назначение свое как универсальный класс для DHTML+AJAX не оправдывает.
А надо мне всего-то узнать ответ 1 или 0.

помотие решить проблемму а не обойти ее
7.
2.1K
25 июля 2006 года
kopex
234 / / 25.07.2006
Мне нравитсяМне не нравится
4 августа 2006, 08:20:29
Надоело с этим бороться, решили просто перейти на использование отлаженной библиотеки Subsys , которую можно скачать с сайта dklab.ru . Там и статейка на эту тему очень интересная прилагается
8.
2.1K
25 июля 2006 года
kopex
234 / / 25.07.2006
+0 / -1
Мне нравитсяМне не нравится
25 июля 2006, 18:16:53
Никто не сталкивался с такой проблемой?
IE 6
function doLoad(uri,obj,dest) {
var req = window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject("Microsoft.XMLHTTP");
req.onreadystatechange = function(){
alert(1);
if (req.readyState == 4) {
obj[dest] = req.responseText;
}

}
req.open("GET", uri+'&ctype=ptext');
req.send(null);
}
При отработке IE пишет что в скрипте ошибка с коментарием "Ошибка: Системная ошибка № -10728996748
Код: 0"
В ФФ код работает без проблем ,не считая ещё одного серьёзного минуса(проблемы с кодировками)
Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог